<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Connor Skennerton</title>
		<link>/</link>
		<description>Recent content on Connor Skennerton</description>
		<generator>Hugo 0.74.1 -- gohugo.io</generator>
		<language>en-us</language>
		<managingEditor>c.skennerton@gmail.com (Connor Skennerton)</managingEditor>
		<webMaster>c.skennerton@gmail.com (Connor Skennerton)</webMaster>
		<copyright>Connor Skennerton — All rights reserved.</copyright>
		<lastBuildDate>Thu, 12 Dec 2024 00:00:00 +0000</lastBuildDate>
		<atom:link href="/index.xml" rel="self" type="application/rss+xml" />
		<item>
			<title>Can we imagine something better than embedded SQL strings</title>
			<link>/2024/12/12/can-we-imagine-something-better-than-embedded-sql-strings/</link>
			<pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2024/12/12/can-we-imagine-something-better-than-embedded-sql-strings/</guid>
			<description>&lt;p&gt;SQL is &lt;em&gt;lingua franca&lt;/em&gt; of the data world. Every tool supports it or has some version of it.  I&amp;rsquo;ve been
exposed to Postres, Trino, Spark-SQL, Flink-SQL, MySql, MS-SQL and they all work the same way for basic
things. Of course the real challenge is when things get more complicated, certain functions have
different names, or don&amp;rsquo;t exist, and some query patterns that work well in one engine don&amp;rsquo;t in another.
(And I don&amp;rsquo;t just mean between OLTP and OLAP engines) While these are minor annoyances, it is pretty
amazing to have a declarative language that is mostly familiar across tools and environments so that
everyone from a product manager to a backend engineer can query terabytes of data in a few seconds.&lt;/p&gt;
&lt;p&gt;Sadly what isn&amp;rsquo;t amazing is all the extra tooling that has been built on top of this in the data
engineering world.  Data Engineering can&amp;rsquo;t just rely on SQL, we need to orchestrate queries and
parameterize them in various different ways. This is often done in Python (e.g. Airflow, Dagster,
Prefect) using some degree of templating, whether that is using &lt;code&gt;jinja2&lt;/code&gt;, &lt;code&gt;f-strings&lt;/code&gt;, or &lt;code&gt;.format()&lt;/code&gt;.
Doing this has drastic negative effects on developer experience becuase we loose even basic things
like syntax highlighting, or more advanded features of static analysis.&lt;/p&gt;
&lt;p&gt;Some IDEs have extensions that detect embedded SQL and apply better linting rules. (Shout out to
&lt;a href=&#34;https://www.jetbrains.com/pycharm/&#34;&gt;Pycharm&lt;/a&gt; which does this and lets you select a wide range of SQL
dialects.) But if you don&amp;rsquo;t have that you&amp;rsquo;re stuck looking at a very long string and trying to understand
why, when it&amp;rsquo;s all stitched together, where the syntax error is.&lt;/p&gt;
&lt;p&gt;SQL itself is not a language that is easily modularized. It is difficult to create chunks or &amp;ldquo;functions&amp;rdquo;
as part of the query.  I&amp;rsquo;ve seen SQL embedding in python as f-strings where whole parts of the query
are generated by calling functions in the string parameters (those functions themselves taking parameters
from the main python code). It&amp;rsquo;s impossible to read but it&amp;rsquo;s done because the original author was
struggling to make something that was composible.&lt;/p&gt;
&lt;p&gt;There are other APIs, &lt;abbr title=&#34;Object Relational Mapping&#34;&gt;ORMs&lt;/abbr&gt; wrap up SQL in more native
looking code and some tools like &lt;a href=&#34;https://spark.apache.org&#34;&gt;Spark&lt;/a&gt; have a data frame API which provides
python native access. I&amp;rsquo;ve found getting out of SQL and using the data frame API quite a productivity
boost but&amp;hellip;&lt;/p&gt;
&lt;p&gt;Because SQL is &lt;em&gt;lingua franca&lt;/em&gt; it is difficult to on board users onto other ways of developing. Any
open source Data or BI tool will accept SQL but ORM wrappers or data frame APIs aren&amp;rsquo;t supported.  I
try to work as much in Spark as possible and use the Dataframe API as much as I can due to it&amp;rsquo;s
composibility, but it is hard to iterate quickly when Trino is just faster at some things and the only
way to use it is via SQL through the company sanctioned web app BI tool.&lt;/p&gt;
&lt;p&gt;Then again, maybe this doesn&amp;rsquo;t matter anymore: I can ask github copilot to take some SQL and convert
it into pyspark Dataframe API, and it does a pretty good job of it&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Helix Shortcuts</title>
			<link>/2024/12/11/helix-shortcuts/</link>
			<pubDate>Wed, 11 Dec 2024 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2024/12/11/helix-shortcuts/</guid>
			<description>&lt;p&gt;Writing these down because I always forget&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;replace-all-occurances-of-something&#34;&gt;Replace all occurances of something&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;create a selection. For example, using &lt;kbd&gt;x&lt;/kbd&gt; for lines, &lt;kbd&gt;v&lt;/kbd&gt; for a flexible selection, or &lt;kbd&gt;%&lt;/kbd&gt; for the whole file&lt;/li&gt;
&lt;li&gt;search in the selection with &lt;kbd&gt;s&lt;/kbd&gt; followed by whatever you want to search for, then &lt;kbd&gt;enter&lt;/kbd&gt;&lt;/li&gt;
&lt;li&gt;(this will create a whole bunch of cursors) use &lt;kbd&gt;c&lt;/kbd&gt; to change the text and enter insert-mode to replace&lt;/li&gt;
&lt;/ol&gt;
</description>
		</item>
		<item>
			<title>Résumé</title>
			<link>/resume/</link>
			<pubDate>Sun, 10 Nov 2024 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/resume/</guid>
			<description>&lt;h2 id=&#34;experience&#34;&gt;Experience&lt;/h2&gt;
&lt;h3 id=&#34;senior-software-engineer&#34;&gt;Senior Software Engineer&lt;/h3&gt;
&lt;h4 id=&#34;roblox-2022---present&#34;&gt;Roblox 2022 - Present&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Part of the core Data Engineering team to build growth accounting and engagement datasets.&lt;/li&gt;
&lt;li&gt;Developed tooling and frameworks to abstract boilerplate of building data pipelines.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;senior-staff-data-engineer&#34;&gt;Senior Staff Data Engineer&lt;/h3&gt;
&lt;h4 id=&#34;pendulum-therapeutics-20192022&#34;&gt;Pendulum Therapeutics 2019 — 2022&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Worked cross functionally with relevant stakeholders at Pendulum to architect the full stack of software and data infrastructure.&lt;/li&gt;
&lt;li&gt;Architected Python libraries to enable data scientists to easily interact with REST APIs and databases.&lt;/li&gt;
&lt;li&gt;Managed junior software engineers, mentored their technical development with pair programming and code reviews while helping to balance their personal career objectives with company goals.&lt;/li&gt;
&lt;li&gt;Led development of internal web applications. Creating the data model, API, and frontend layer.&lt;/li&gt;
&lt;li&gt;Developed ETL and ELT pipelines for integrating Marketing, Manufacturing, and R&amp;amp;D data from SaaS applications and internal databases into a Snowflake data warehouse using Luigi, Prefect, and DBT.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;bioinformatics-cloud-engineer&#34;&gt;Bioinformatics Cloud Engineer&lt;/h3&gt;
&lt;h4 id=&#34;second-genome-2018--2019&#34;&gt;Second Genome 2018 — 2019&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Converted bioinformatics pipelines for processing genomic and metagenomic data into serverless, containerized applications using Docker, AWS Batch, AWS Lambda, AWS SQS.&lt;/li&gt;
&lt;li&gt;Spearheaded python code consolidation within the company into a single unified library, enforcing test-driven development and software development lifecycle practices.&lt;/li&gt;
&lt;li&gt;Developed ETL pipelines to automatically scrape NCBI and IMG databases and integrate them with private datasets into data warehouses&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;postdoctoral-research-fellow&#34;&gt;Postdoctoral Research Fellow&lt;/h3&gt;
&lt;h4 id=&#34;caltech-20142018&#34;&gt;Caltech 2014―2018&lt;/h4&gt;
&lt;p&gt;My role was the head bioinformatician for a diverse group of microbiologists, chemists and data scientists at the California Institute of Technology (Caltech). My day to day tasks included the processing of genomic and proteomic data, and generating analysis summaries and plots using statistical software and programing tools such as R and python. As part of this role I was responsible for the production of automated pipelines for data analysis and have developed numerous tools and scripts for processing genomic data. I implemented SQL databases to store the extensive genomic and proteomic data that were generated and developed simple interfaces such that other members of the group could access this information without in-depth knowledge of SQL.&lt;/p&gt;
&lt;h3 id=&#34;graduate-student&#34;&gt;Graduate Student&lt;/h3&gt;
&lt;h4 id=&#34;university-of-quensland-20102014&#34;&gt;University of Quensland 2010―2014&lt;/h4&gt;
&lt;p&gt;My PhD research focused on metagenomic analysis of microbial and viral communities from engineered ecosystems found in wastewater treatment plants. Throughout my PhD I was at the interface of microbial ecology, chemical engineering, and computational biology and have gained many skills ranging from microscopy, reactor operation and computer programming. I developed a number of bioinformatic pipelines and substantial computer software in perl, python and C++. My background in molecular biology allowed me to place the inferences of metagenomic data into a broader biological framework and work with other members of the lab that did not have computer skills.&lt;/p&gt;
&lt;h2 id=&#34;education&#34;&gt;Education&lt;/h2&gt;
&lt;h3 id=&#34;university-of-queensland&#34;&gt;University of Queensland&lt;/h3&gt;
&lt;p&gt;2014, PhD in Microbial Ecology&lt;/p&gt;
&lt;p&gt;2010, Bachelor of Biotechnology&lt;/p&gt;
&lt;h3 id=&#34;honors--awards&#34;&gt;Honors &amp;amp; Awards&lt;/h3&gt;
&lt;p&gt;2015, Dean&amp;rsquo;s award for outstanding PhD dissertation, University of Queensland&lt;/p&gt;
&lt;p&gt;2010, Australian Research Council PhD Fellowship&lt;/p&gt;
&lt;h2 id=&#34;publications&#34;&gt;Publications&lt;/h2&gt;
&lt;p&gt;McMurdie, P. J., Stoeva, M. K., Justice, N., Nemchek, M., Sieber, C. M. K., Tyagi, S., Gines J., &lt;strong&gt;Skennerton, C. T.,&lt;/strong&gt; Souza, M., Kolterman, O., Eid, J. (2022). &amp;ldquo;&lt;a href=&#34;https://doi.org/10.1186/s12866-021-02415-8&#34;&gt;Increased circulating butyrate and ursodeoxycholate during probiotic intervention in humans with type 2 diabetes&lt;/a&gt;&amp;rdquo;. BMC Microbiol 22, 19 (2022).&lt;/p&gt;
&lt;p&gt;Chadwick, G. L., &lt;strong&gt;Skennerton, C. T.,&lt;/strong&gt; Laso-Pérez, R., Leu, A. O., Speth, D. R., Yu, H., Morgan-Lang, C., Hatzenpichler, R., Goudeau, D., Malmstrom, R., Brazelton, W. J., Woyke, T., Hallam, S. J., Tyson, G. W., Wegener, G., Boetius, A., Orphan, V. J. (2022) &amp;ldquo;&lt;a href=&#34;https://doi.org/10.1371/journal.pbio.3001508&#34;&gt;Comparative genomics reveals electron transfer and syntrophic mechanisms differentiating methanotrophic and methanogenic archaea&lt;/a&gt;&amp;rdquo;. PLoS Biol 20(1): e3001508.&lt;/p&gt;
&lt;p&gt;Yu, H., &lt;strong&gt;Skennerton, C. T.,&lt;/strong&gt; Chadwick, G. L., Leu, A. O., Aoki, M., Tyson, G. W., Orphan, V. J. (2022) &amp;ldquo;&lt;a href=&#34;https://pubmed.ncbi.nlm.nih.gov/34285362/&#34;&gt;Sulfate differentially stimulates but is not respired by diverse anaerobic methanotrophic archaea&lt;/a&gt;&amp;rdquo;. ISME J 16(1): 168-177.&lt;/p&gt;
&lt;p&gt;Sim, M., &lt;strong&gt;Skennerton, C. T.,&lt;/strong&gt; Orphan, V. J. (2021) &amp;ldquo;&lt;a href=&#34;https://pubmed.ncbi.nlm.nih.gov/33444327/&#34;&gt;Physiological, genomic, and sulfur isotopic characterization of methanol metabolism by Desulfovibrio carbinolicus&lt;/a&gt;&amp;rdquo;. PLoS ONE. 16(1): e0245069&lt;/p&gt;
&lt;p&gt;Yu, H., Susanti, D., McGlynn, S. E., &lt;strong&gt;Skennerton, C. T.,&lt;/strong&gt; Chourey, K., Iyer, R., Scheller, S., Tavormina, P. L., Hettich, R. L., Mukhopadhyay, B., Orphan V. J. (2018) &amp;ldquo;&lt;a href=&#34;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6286981/&#34;&gt;Comparative Genomics and Proteomic Analysis of Assimilatory Sulfate Reduction Pathways in Anaerobic Methanotrophic Archaea&lt;/a&gt;&amp;rdquo;. Frontiers Microbiol. 9: 2917&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Chourey, K., Iyer, R., Hettich, R. L., Tyson, G. W., Orphan, V. J. (2017) &amp;ldquo;&lt;a href=&#34;https://www.ncbi.nlm.nih.gov/pubmed/28765215&#34;&gt;Methane-Fueled Syntrophy through Extracellular Electron Transfer: Uncovering the Genomic Traits Conserved within Diverse Bacterial Partners of Anaerobic Methanotrophic Archaea&lt;/a&gt;&amp;rdquo;. mBio 8(4):e00530-17&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Haroon, M. F., Briegel, A., Shi, J., Jensen, G. J., Tyson, G. W., Orphan, V. J. (2016) &amp;ldquo;&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/27058507&#34;&gt;Phylogenomic analysis of &lt;em&gt;Candidatus&lt;/em&gt; ‘Izimaplasma’ species: free-living representatives from a Tenericutes clade found in methane seeps&lt;/a&gt;&amp;rdquo;. ISMEJ. 10: 2679–2692&lt;/p&gt;
&lt;p&gt;Marlow, J. J., &lt;strong&gt;Skennerton, C. T.,&lt;/strong&gt; Li, Z., Chourey, K., Hettich, R. L., Pan, C., Orphan, V. J. (2016). &amp;ldquo;&lt;a href=&#34;http://journal.frontiersin.org/article/10.3389/fmicb.2016.00563/full&#34;&gt;Proteomic Stable Isotope Probing Reveals Biosynthesis Dynamics of Slow Growing Methane Based Microbial Communities&lt;/a&gt;&amp;rdquo;. Frontiers Microbiol. 7: 563&lt;/p&gt;
&lt;p&gt;Barr, J. J., Dutilh, B. E., &lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Fukushima, T., Hastie, M. L., Gorman, J. J., Tyson, G. W., Bond, P. L. (2016). “&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/26279094&#34;&gt;Metagenomic and metaproteomic analyses of Accumulibacter phosphatis enriched floccular and granular biofilm&lt;/a&gt;”. Environ. Microbiol. 18(1): 273–287&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Skennerton, C. T.,&lt;/strong&gt; Ward, L. M., Michel, A., Metcalfe, K., Valiente, C., Mullin, S., Chan, K. Y., Gradinaru, V., Orphan, V. J. (2015). &amp;ldquo;&lt;a href=&#34;http://journal.frontiersin.org/article/10.3389/fmicb.2015.01425/full&#34;&gt;Genomic Reconstruction of an Uncultured Hydrothermal Vent Gammaproteobacterial Methanotroph (Family &lt;em&gt;Methylothermaceae&lt;/em&gt;) Indicates Multiple Adaptations to Oxygen Limitation&lt;/a&gt;&amp;quot;. Frontiers Microbiol. 6&lt;/p&gt;
&lt;p&gt;Parks, D. H., Imelfort, M., &lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Hugenholtz, P., Tyson, G. W. (2015). “&lt;a href=&#34;http://genome.cshlp.org/content/25/7/1043.long&#34;&gt;CheckM: assessing the quality of microbial genomes recovered from isolates, single cells, and metagenomes&lt;/a&gt;”. Genome Res. 25: 1043–1055.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Barr, J. J., Slater, F. R., Bond, P. L., Tyson, G. W. (2015). “&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/25088527&#34;&gt;Expanding our view of genomic diversity in &lt;em&gt;Candidatus&lt;/em&gt; Accumulibacter clades&lt;/a&gt;”. Environ. Microbiol. 17 (5): 1574–1585.&lt;/p&gt;
&lt;p&gt;Soo, R. M., &lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Sekiguchi, Y., Imelfort, M., Paech, S. J., Dennis, P. G., Steen, J. A., Parks, D. H., Tyson, G. W., Hugenholtz, P. (2014). “&lt;a href=&#34;http://gbe.oxfordjournals.org/content/6/5/1031.long&#34;&gt;An expanded genomic representation of the phylum cyanobacteria&lt;/a&gt;”. Genome Biol. Evol. 6 (5): 1031– 1045.&lt;/p&gt;
&lt;p&gt;Haroon, M. F., &lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Steen, J. A., Lachner, N., Hugenholtz, P., Tyson, G. W. (2013). “&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/24060113&#34;&gt;In-Solution Fluorescence In Situ Hybridization and Fluorescence-Activated Cell Sorting for Single Cell and Population Genome Recovery&lt;/a&gt;”. In: Microbial Metagenomics, Metatranscriptomics, and Metaproteomics. Ed. by Edward F. DeLong. Vol. 531. Academic Press, 3–19.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Imelfort, M., Tyson, G. W. (2013). “&lt;a href=&#34;http://nar.oxfordjournals.org/content/41/10/e105.long&#34;&gt;Crass: identification and reconstruction of CRISPR from unassembled metagenomic data&lt;/a&gt;”. Nucleic Acids Res. 41 (10): e105.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Skennerton, C. T.&lt;/strong&gt;, Angly, F. E., Breitbart, M., Bragg, L., He, S., McMahon, K. D., Hugenholtz, P., Tyson, G. W. (2011) “&lt;a href=&#34;http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0020095&#34;&gt;Phage encoded H-NS: a potential achilles heel in the bacterial defence system&lt;/a&gt;”. PLoS One, 6 (5): e20095.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Trying out Helix as my text editor</title>
			<link>/2023/07/09/trying-out-helix-as-my-text-editor/</link>
			<pubDate>Sun, 09 Jul 2023 15:00:00 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2023/07/09/trying-out-helix-as-my-text-editor/</guid>
			<description>&lt;p&gt;&lt;a href=&#34;https://helix-editor.com&#34;&gt;Helix&lt;/a&gt; is a modal editor in the same vein as Vim which means that there are different &amp;ldquo;modes&amp;rdquo; where
the same key strokes mean different things. The main benefit for a modal editor is that many complex
actions can be handled with just the keyboard rather than using the mouse or menus.
I&amp;rsquo;ve been a Vim user for over a decade so I was interested to see what a modal editor that doesn&amp;rsquo;t
come from that lineage would look like. My motivation was the complexity of getting my Neovim
config set up just right when working with language servers and tree-sitter. Helix had these
features built in so I wanted to see if Helix could improve my productivity without having to
mess around with a lot of plugins.&lt;/p&gt;
&lt;p&gt;I installed helix using homebrew as recommended (&lt;kbd&gt;brew install helix&lt;/kbd&gt;). Initally I was confused
about the command I needed to run. Turns out that it isn&amp;rsquo;t Helix but &lt;code&gt;hx&lt;/code&gt;. The documentation
directed me to use the tutorial with &lt;code&gt;hx --tutor&lt;/code&gt; and I&amp;rsquo;m glad I did as it presented the editing
commands in a logical and easy way. I did want to skip ahead at some points as I was familiar with
and there are many similarities but as you get further through the differences show up. You&amp;rsquo;ll want to
keep a link to the &lt;a href=&#34;https://docs.helix-editor.com/keymap.html&#34;&gt;keymap&lt;/a&gt; handy.
The are basic similarities in the key bindings but in helix the grammar is often reversed.
For example, instead of typing &lt;kbd&gt;dw&lt;/kbd&gt; you would type &lt;kbd&gt;wd&lt;/kbd&gt;. This small change is really interesting
as you can see what you are selecting (and potentially modify it) before doing anything
destructive. It&amp;rsquo;s sort of like having Vim visual mode always being on.
Comands that normally move the cursor in vim will change the selection in helix. So, &lt;kbd&gt;w&lt;/kbd&gt;
won&amp;rsquo;t just move to the end of the word but instead select the whole word. For basic incantations
like &lt;kbd&gt;dw&lt;/kbd&gt; (in Vim) or &lt;kbd&gt;wd&lt;/kbd&gt; (in Helix) this will have the same effect - the word will be deleted.&lt;/p&gt;
&lt;p&gt;The muscle memory from Vim to Helix can be tough. In particular, I&amp;rsquo;m fond of typing &lt;kbd&gt;x&lt;/kbd&gt; to delete
a single character and &lt;kbd&gt;gg&lt;/kbd&gt; (or &lt;kbd&gt;G&lt;/kbd&gt;) to move to parts of the current file. Having these be different
things in Helix took some getting used to. But not in a bad way. I enjoy Helix take on &lt;code&gt;g&lt;/code&gt; command
to let me move to all parts of the line or file. The mnemonic for &lt;code&gt;g&lt;/code&gt; being &amp;ldquo;go&amp;rdquo; in Helix versus &amp;ldquo;global&amp;rdquo;
in Vim seems more natural to me.
I do miss marks though. A very common workflow for me was setting locations in Vim using &lt;kbd&gt;ma&lt;/kbd&gt; or &lt;kbd&gt;mb&lt;/kbd&gt;
to jump around a buffer. In Helix, &lt;code&gt;m&lt;/code&gt; is for entering &amp;ldquo;match mode&amp;rdquo; that lets you select different parts
of the buffer. It&amp;rsquo;s very useful just hard to break habits. There currently isn&amp;rsquo;t an equivelent to vim&amp;rsquo;s
marks in helix. Instead you can save locations in a jump list using &lt;kbd&gt;Crtl&lt;/kbd&gt; + &lt;kbd&gt;s&lt;/kbd&gt; and then returning
to those locations using &lt;kbd&gt;Space&lt;/kbd&gt; + &lt;kbd&gt;j&lt;/kbd&gt; and choosing them from a pop up dialog. It&amp;rsquo;s certainly not
as fast so I hope the helix developers consider having named marks in the future.&lt;/p&gt;
&lt;p&gt;The other issue I ran into was the default python configuration requires &lt;code&gt;pylsp&lt;/code&gt; which doesn&amp;rsquo;t
work well with my setup that uses &lt;code&gt;pyenv&lt;/code&gt;.
Because I use per-project python environments but &lt;code&gt;pyenv&lt;/code&gt; creates a shim in my path which Helix
picks up and uses. The language server command needs to be in your path and I couldn&amp;rsquo;t figure out
how to get it to work without installing &lt;code&gt;pylsp&lt;/code&gt; into all of my environments. I ended up using
&lt;code&gt;pywright&lt;/code&gt; which I installed globally through &lt;code&gt;npm&lt;/code&gt;. It&amp;rsquo;s not the cleanest solution but it works.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;brew install helix npm
npm install --location&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;global pyright
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;config&#34;&gt;Config&lt;/h2&gt;
&lt;h3 id=&#34;confighelixconfigtoml&#34;&gt;&lt;code&gt;~/.config/helix/config.toml&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;nx&#34;&gt;theme&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;noctis&amp;#34;&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;editor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;number&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;absolute&amp;#34;&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;editor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;cursor&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;shape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;insert&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;bar&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;normal&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;block&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;select&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;underline&amp;#34;&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;editor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;picker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;hidden&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;confighelixlanguagestoml&#34;&gt;&lt;code&gt;~/.config/helix/languages.toml&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;language&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;python&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;scope&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;source.python&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;injection&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;regex&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;python&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;types&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;pyi&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;py3&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;pyw&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ptl&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.pythonstartup&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.pythonrc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;SConstruct&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;shebangs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;python&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;roots&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;setup.py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;setup.cfg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pyproject.toml&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;comment&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;token&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;language&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;server&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;command&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pyright-langserver&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;args&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;--stdio&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;indent&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;tab&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;unit&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;    &amp;#34;&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;# will get &amp;#34;Async jobs timed out&amp;#34; errors if this empty config is not added&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;config&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
		<item>
			<title>Building a personal baby tracker with Pharo and Seaside</title>
			<link>/2023/05/29/building-a-personal-baby-tracker-with-pharo-and-seaside/</link>
			<pubDate>Mon, 29 May 2023 12:35:00 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2023/05/29/building-a-personal-baby-tracker-with-pharo-and-seaside/</guid>
			<description>&lt;p&gt;One of the things that I&amp;rsquo;ve discovered about parenting is that
babies are tracked religously. How much are they sleeping? Are they
eating enough? Did they pee/poop the correct number of times in the
last 24 hours? This isn&amp;rsquo;t just frettful new parent stuff (although
it totally is that too) but things that pediatricians want to know
and could be the early signs of problems when there isn&amp;rsquo;t a good
way to know if there is a problem. There are many apps that will
help with this giving simple GUI to measure all sorts of things.
&lt;a href=&#34;https://babytracker.info/&#34;&gt;Here&lt;/a&gt; is a website that compares some,
and a quick search of the App Store will give many more. The problem
I have with all of these solutions is that you are minutely tracking
the first stages of your childs life and development and giving all
that data to someone else. The people who make these apps are running
a business and you&amp;rsquo;re the product. Now I don&amp;rsquo;t necessarily have an
issue with that, I&amp;rsquo;m using multiple apps that work by targeting ads
to me. I get it, but I didn&amp;rsquo;t want to feed the personal data mining
machine. I didn&amp;rsquo;t want to read a privacy policy or even worry about
it, I wanted something where there was no data to be given away and
sold. So I wrote &lt;a href=&#34;https://github.com/ctSkennerton/baby_tracker&#34;&gt;my own personal baby tracker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The requirements were pretty simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Dead easy UI so even in a sleep deprived state we could log updates.&lt;/li&gt;
&lt;li&gt;Available across multiple devices.&lt;/li&gt;
&lt;li&gt;Only accessible to people caring for our newborn.&lt;/li&gt;
&lt;li&gt;Easy development and deployment. This is a personal project so it doesn&amp;rsquo;t need to scale.&lt;/li&gt;
&lt;li&gt;Have some fun.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I wrote an MVP that works for me using the Seaside framework with
&lt;a href=&#34;https://pharo.org&#34;&gt;Pharo&lt;/a&gt; 10.  This was my first time using Seaside
and I was really impressed with how easy it was to generate pages.
No need to learn a templating language like in Python or Ruby.
Instead, in Seaside, you write the HTML structure using smalltalk
code.  There was a big learning curve for me because of some initial
misconceptions about how Seaside works.  It&amp;rsquo;s not just for creating
web pages, but for creating web apps. In Django/Flask or other
frameworks I&amp;rsquo;ve used the request contains all of the information
and state isn&amp;rsquo;t saved. In Seaside, state is saved, I found that
thinking about Seaside to how something like React or Vue are used;
there is global state and this is saved for you between actions.
The difference being that Seaside acts server-side.&lt;/p&gt;
&lt;p&gt;Seaside doesn&amp;rsquo;t provide any persistence like Django or Ruby on
Rails. In that regard it&amp;rsquo;s a bit more like Flask. Pharo has many
libraries for persistence I chose
&lt;a href=&#34;https://github.com/rko281/ReStoreForPharo&#34;&gt;ReStore&lt;/a&gt; as it looked
easy to set up. And it was! ReStore has a simple API that mimics
the collection API in Pharo but it also allowed for some interesting
customizations. ReStore has a simple way to add
translations for Smalltalk messages into SQL functions or expressions.
I was able to add in sqlite3&amp;rsquo;s &lt;code&gt;unixepoch&lt;/code&gt; function by using the
&lt;code&gt;asUnixTime&lt;/code&gt; message that is understood by the &lt;code&gt;DateAndTime&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nc&#34;&gt;ReStore&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;translateMessage:&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;#asUnixTime&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;toFunction:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;UNIXEPOCH(%1)&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asSQLFunctionIntegerResult&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nc&#34;&gt;ReStore&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;translateMessage:&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;#asDate&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;toFunction:&lt;/span&gt; (&lt;span class=&#34;s&#34;&gt;&amp;#39;date(%1)&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asSQLFunctionWithResultClass:&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Date&lt;/span&gt;)&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

(&lt;span class=&#34;nc&#34;&gt;BabyEvent&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;storedInstances&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;satisfying:&lt;/span&gt; [
    &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;startTime&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;2022-10-29&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asDate&lt;/span&gt; ] )
    &lt;span class=&#34;nf&#34;&gt;project:&lt;/span&gt; [
        &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;
        &lt;span class=&#34;nv&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;startDate&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;durationInSeconds&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sum&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;durationInSeconds&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;average&lt;/span&gt; 
    ]&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This kind of customization was increadably simple. I have no idea
how I could have done this in something like Django (or whether
such a thing is even possible).&lt;/p&gt;
&lt;p&gt;One of the difficulties when using a more niche framework is the
lack of documentation for all of the use cases. One top of that
this was my first Seaside app, so trying to map my knowledge from
Django took a little time. For example, I couldn&amp;rsquo;t figure out how
to keep track of the database connection, or where to store such
initialization information. After asking a few &amp;ldquo;stupid questions&amp;rdquo;
I was pointed to using the &lt;code&gt;WASession&lt;/code&gt; class to hold &amp;ldquo;global&amp;rdquo;
information like the database connection. Here are a couple of links
I was pointed to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://onsmalltalk.com/terse-guide-to-seaside&#34;&gt;http://onsmalltalk.com/terse-guide-to-seaside&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://edutec.citilab.eu/downloads/TFC-ASmalltalkByTheSeaside.pdf&#34;&gt;https://edutec.citilab.eu/downloads/TFC-ASmalltalkByTheSeaside.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Though I found that the &lt;a href=&#34;https://github.com/svenvc/Reddit&#34;&gt;Reddit&lt;/a&gt;
sample application for seaside is a great resource for looking at
the session and the deployment.&lt;/p&gt;
&lt;p&gt;For deployment I found &lt;a href=&#34;https://nickjanetakis.com/blog/why-i-prefer-running-nginx-on-my-docker-host-instead-of-in-a-container&#34;&gt;this blog&lt;/a&gt; nice for not running nginx and I used Digital Ocean&amp;rsquo;s tool
for creating the actual configuration (as well as their hosting to set up a small droplet)&lt;/p&gt;
</description>
		</item>
		<item>
			<title>About Me</title>
			<link>/about/</link>
			<pubDate>Tue, 15 Nov 2022 09:15:00 -0800</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/about/</guid>
			<description>&lt;p&gt;I am a Data Engineer currently working at &lt;a href=&#34;http://roblox.com&#34;&gt;Roblox&lt;/a&gt;.
I received my PhD at &lt;a href=&#34;http://uq.edu.au&#34;&gt;UQ&lt;/a&gt; in the &lt;a href=&#34;http://ecogenomic.org&#34;&gt;Australian Centre for Ecogenomics&lt;/a&gt;. Throughout my PhD I was at the
interface of microbial ecology, chemical engineering, and computational
biology and have gained many skills ranging from microscopy, reactor
operation and computer programming.&lt;/p&gt;
&lt;p&gt;During my PhD, I developed many data analysis skills, including
statistical inference, programming, and developing novel bioinformatics
algorithms. I further honed these skills as a postdoctoral researcher
at Caltech developing a SQL database to integrate diverse data
sources while mentoring PhD students in bioinformatics.&lt;/p&gt;
&lt;p&gt;I transitioned to working in industry at Second Genome where I used
my bioinformatics knowledge to implement scalable data analysis
workflows in AWS. At Pendulum Therapeutics I was involved in
all aspects of the software and data stack including full-stack
development of internal web applications, ETL and ELT pipelines,
data warehousing, third-party data integrations, deployment/devops
on AWS, and reporting and analytics.&lt;/p&gt;
&lt;p&gt;I’m fluent in Python, however I have written software in diverse
languages including Javascript, Typescript, Perl, R, Smalltalk,
Java, and C++. As part of my duties I regularly collaborate with
members of the scientific team and with non-technical members of
the company to understand user requirements and build solutions for
laboratory and manufacturing teams. I am passionate about analysis
automation, eﬀicient data processing, and believe strongly in version
control, test-driven development, and literate programming techniques
to ensure reproducibility.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Datelist tables at Roblox Data Engineering Meetup</title>
			<link>/2022/09/29/datelist-tables-at-roblox-data-engineering-meetup/</link>
			<pubDate>Thu, 29 Sep 2022 08:00:00 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2022/09/29/datelist-tables-at-roblox-data-engineering-meetup/</guid>
			<description>&lt;p&gt;Yesterday I went to a data engineering meetup hosted by &lt;a href=&#34;https://www.roblox.com&#34;&gt;Roblox&lt;/a&gt;. The
talk in the meetup was by &lt;a href=&#34;https://www.linkedin.com/in/ynshn/&#34;&gt;Yan Shen&lt;/a&gt; and &lt;a href=&#34;https://www.linkedin.com/in/william-ng-337a9525/&#34;&gt;William Ng&lt;/a&gt; on how they cut down on processing
costs in their data processing pipelines by making use of datelist
tables.&lt;/p&gt;
&lt;p&gt;A datelist table acts as an intermediate incremental accumulating
aggregate of a quantity from a fact table. Their key feature is
that they have a column that contains an array or map of dates where
the this quantity was observed.&lt;/p&gt;
&lt;p&gt;Consider a raw fact table like (but imagine that it&amp;rsquo;s huge and partitioned by day):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;userid&lt;/th&gt;
&lt;th&gt;date&lt;/th&gt;
&lt;th&gt;quantity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2022-09-01&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2022-09-01&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2022-09-04&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2022-09-05&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A datelist table would convert this information into a summary like:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;userid&lt;/th&gt;
&lt;th&gt;fisrt_date&lt;/th&gt;
&lt;th&gt;last_date&lt;/th&gt;
&lt;th&gt;date_list&lt;/th&gt;
&lt;th&gt;dt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2022-09-01&lt;/td&gt;
&lt;td&gt;2022-09-05&lt;/td&gt;
&lt;td&gt;{&amp;ldquo;2022-09-01&amp;rdquo;: 1, &amp;ldquo;2022-09-04&amp;rdquo;: 6, &amp;ldquo;2022-09-05&amp;rdquo;: 5}&lt;/td&gt;
&lt;td&gt;2022-09-05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2022-09-01&lt;/td&gt;
&lt;td&gt;2022-09-01&lt;/td&gt;
&lt;td&gt;{&amp;ldquo;2022-09-01&amp;rdquo;: 5}&lt;/td&gt;
&lt;td&gt;2022-09-05&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In this case the table granularity is an individual user (one user
per row) and contains a column recording all of the dates at which
quantity has been recorded. This table also has a partitioning
column &lt;code&gt;dt&lt;/code&gt; that is used to record the date at which the rows were
last updated. The table can also record other important attributes, in
this case the first date and last date that the quantity was recorded.&lt;/p&gt;
&lt;p&gt;The value in this structure comes from updating the information when
new partitions are added to the original fact table. Let&amp;rsquo;s say that
new data comes in that looks like the following:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;userid&lt;/th&gt;
&lt;th&gt;date&lt;/th&gt;
&lt;th&gt;quantity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2022-09-06&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We can then update the datelist table using only this new partition of the fact table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;userid&lt;/th&gt;
&lt;th&gt;fisrt_date&lt;/th&gt;
&lt;th&gt;last_date&lt;/th&gt;
&lt;th&gt;date_list&lt;/th&gt;
&lt;th&gt;dt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2022-09-01&lt;/td&gt;
&lt;td&gt;2022-09-05&lt;/td&gt;
&lt;td&gt;{&amp;ldquo;2022-09-01&amp;rdquo;: 1, &amp;ldquo;2022-09-04&amp;rdquo;: 6, &amp;ldquo;2022-09-05&amp;rdquo;: 5}&lt;/td&gt;
&lt;td&gt;2022-09-06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2022-09-01&lt;/td&gt;
&lt;td&gt;2022-09-06&lt;/td&gt;
&lt;td&gt;{&amp;ldquo;2022-09-01&amp;rdquo;: 5, &amp;ldquo;2022-09-06&amp;rdquo;: 9}&lt;/td&gt;
&lt;td&gt;2022-09-06&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This can be achieved incrementally as the datelist table contains
all of the history, so to generate the current datelist table we
need only the previous days datelist table and the current partition
of the fact table.&lt;/p&gt;
&lt;p&gt;For small datasets, it&amp;rsquo;s possible to easily scan over the historical
data, but as the dataset grows that becomes an unreasonable compute
burden. In his talk, Yan and WIlliam gave the example of scanning
over a raw fact table that had 10 TB of data generated per day.
Scanning all the historical data every time a query was run required
looking at petabytes of data. In comparison, using datelist table
they only needed to scan through 10TB + ~0.5TB per day.&lt;/p&gt;
&lt;p&gt;The datelist table can then act as an efficient intermediate table
for calculating historical metrics like retention and totals of the
quantity over the last 7 days, 28 days etc., from the table above
it&amp;rsquo;s easy to aggregate the quantity over the previous 7 days:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;userid&lt;/th&gt;
&lt;th&gt;quantity_L7&lt;/th&gt;
&lt;th&gt;dt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;2022-09-06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;2022-09-06&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
		</item>
		<item>
			<title>Tracking down strange out of memory errors in AWS Batch</title>
			<link>/2022/08/28/tracking-down-strange-out-of-memory-errors-in-aws-batch/</link>
			<pubDate>Sun, 28 Aug 2022 22:09:45 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2022/08/28/tracking-down-strange-out-of-memory-errors-in-aws-batch/</guid>
			<description>&lt;p&gt;Recently, one of my colleagues came to me with a mysterious problem
they were having with one of our production tasks running on AWS
Batch. This particular task would be launched based on user interaction
in a internal web application and run a fairly hefty machine
learning model in docker container. Recently, this job started
failing, not all the time, but sometimes on larger input files the
job would fail with an out of memory error. My colleague came to
me because they could run the same Docker container on their local
machine without error so it seemed like an issue specific to the
production environment.&lt;/p&gt;
&lt;p&gt;To understand a little about AWS Batch: you create Docker containers
and then specify a &amp;ldquo;job definition&amp;rdquo; that holds additional information
about how to run that container, such as the amount of RAM, number
of CPUs, environment variables, etc.  This information can be
overridden on a per job basis as well, which makes the system
flexible in cases where there is a much large dataset to process.
The jobs themselves are for batch processing, like taking input
files and performing complex and timer consuming transformations
on them. Jobs get submitted to a queue and the AWS Batch scheduler
will attempt to pack as many of the containers onto one instance
to minimize the amount of left over resources.&lt;/p&gt;
&lt;p&gt;First up, I confirmed that the code did run without issue on an ec2
machine. And I got intrigued by the mystery because the ec2 machine
definitely had less memory than the Batch job was set up to use.
So why was the production job failing?&lt;/p&gt;
&lt;p&gt;Okay, so how about just upping the memory in the Batch job? Can we
just push this through to unblock our customers. By default, we run
the production job with 64Gb of RAM, so I tried 128, 256, 512 Gb
of memory&amp;hellip; Nope, out of memory. Now there is no way that this job
could be using that much RAM and no way that there is that much
difference between running it on an ec2 and Batch (I mean, there
should be none).&lt;/p&gt;
&lt;p&gt;I looked at the ec2 dashboard and found that the instance trying
to run the job was way smaller than expected, in fact it only had
a 2 Gb of RAM. Wait, what. How come the instance that Batch launched
was way smaller than the one that it would need to run the job. To
double check I went back into the AWS Batch console, clicked on the
individual job details and then strolled down to the container limit
section. There I saw a helpful little exclamation mark saying that
the way we passed in container overrides had been depreciated and
that it was falling back to default values.&lt;/p&gt;
&lt;p&gt;And so the mystery was revealed, the large RAM values weren&amp;rsquo;t ever
being taken into account. It would have been nice if these jobs
failed straight away instead of silently being accepted in a corrupted
state.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/media/2022/08/batch-job-warning.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Creating an AWS SDK for Pharo Smalltalk</title>
			<link>/2022/04/02/creating-an-aws-sdk-for-pharo-smalltalk/</link>
			<pubDate>Sat, 02 Apr 2022 14:52:00 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2022/04/02/creating-an-aws-sdk-for-pharo-smalltalk/</guid>
			<description>&lt;p&gt;I&amp;rsquo;ve been working on an expanded AWS SDK for Pharo. Currently, 234 AWS services are available. See
the code on &lt;a href=&#34;https://github.com/ctSkennerton/aws-sdk-smalltalk&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Amazon Web Services (AWS) is a huge set (approximately 300 at time of writing) of services for doing
just about anything related to computing infrastructure and tools, often with multiple ways to
achieve the same or similar thing. The awesome thing about AWS is that there is an extensive set of
APIs for working with these services that make it a coders paradise since it opens up great avennues
for automation. The AWS APIs are implemented via HTTP which means that they can be accessed
basically from any programming language that lets you send and receive web requests. However it&amp;rsquo;s
much nicer to wrap up these API calls into software development kits (SDKs) that hide a lot of those
details. AWS has a lot of officially supported languages and there are also some community efforts
for other lanuages. Sadly, there isn&amp;rsquo;t a complete SDK for Smalltalk, although there is a &lt;a href=&#34;https://github.com/newapplesho/aws-sdk-smalltalk&#34;&gt;incomplete
version on Github&lt;/a&gt; that has partial support for
some services. I wanted to expand on this but the task seems hurculean since there are thousands of
APIs that need to be written.&lt;/p&gt;
&lt;h2 id=&#34;how-does-aws-manage-all-its-sdks&#34;&gt;How does AWS manage all its SDKs?&lt;/h2&gt;
&lt;p&gt;AWS is a big company but I still wanted to understand how they could release the same set of APIs in
all these different programming languages and keep them all in sync. Thankfully, the SDKs are all
open source so I looked through how the Python SDK,
&lt;a href=&#34;https://boto3.amazonaws.com/v1/documentation/api/latest/index.html&#34;&gt;Boto3&lt;/a&gt;, is created. Boto3
actually relies on a separate package called &lt;a href=&#34;https://github.com/boto/botocore&#34;&gt;botocore&lt;/a&gt; that
handles all of the lower level HTTP API calls. If you&amp;rsquo;ve ever done &lt;code&gt;boto3.client(&#39;batch&#39;)&lt;/code&gt; in
Python, you&amp;rsquo;re actually using the code in botocore.&lt;/p&gt;
&lt;p&gt;Botocore makes heavy use of code generation! The &lt;a href=&#34;https://github.com/boto/botocore/tree/develop/botocore/data&#34;&gt;AWS APIs are defined in JSON formatted
files&lt;/a&gt; and this data is read at runtime
to dynamically create the correct classes. Looking at other languages, like
&lt;a href=&#34;https://github.com/aws/aws-sdk-ruby/tree/version-3/apis&#34;&gt;Ruby&lt;/a&gt; or
&lt;a href=&#34;https://github.com/aws/aws-sdk-go/tree/main/models/apis&#34;&gt;Go&lt;/a&gt;, there are the exact same files.&lt;/p&gt;
&lt;p&gt;Aha! AWS doesn&amp;rsquo;t make these SDKs individually, they publish data files that enable code generation.&lt;/p&gt;
&lt;h2 id=&#34;understanding-the-data-files&#34;&gt;Understanding the data files&lt;/h2&gt;
&lt;p&gt;For each service there are multiple JSON files but the main one seems to be &lt;code&gt;service-2.json&lt;/code&gt;. This
file contains information about the &amp;ldquo;operations&amp;rdquo;, the API endpoints for the service, and the
&amp;ldquo;shapes&amp;rdquo;, which describe the input and output data structures for the API requests. There is also a
&amp;ldquo;metadata&amp;rdquo; section with lots of interesting things about the service itself.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;apiVersion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;2020-08-01&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;endpointPrefix&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;aps&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;jsonVersion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1.1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;protocol&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;rest-json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;serviceFullName&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Amazon Prometheus Service&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;serviceId&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;amp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;signatureVersion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;v4&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;signingName&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;aps&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;amp-2020-08-01&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;operations&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{},&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;shapes&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The metadata has a &lt;code&gt;protocol&lt;/code&gt; key that broadly describes how to construct API requests and
deserializing responses.  There are five different protocols listed in the data files that AWS
services use to construct queries: &amp;lsquo;json&amp;rsquo;, &amp;lsquo;ec2&amp;rsquo;, &amp;lsquo;rest-xml&amp;rsquo;, &amp;lsquo;rest-json&amp;rsquo;, &amp;lsquo;query&amp;rsquo;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol Name&lt;/th&gt;
&lt;th&gt;Services Using Protocol&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;rest-json&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;json&lt;/td&gt;
&lt;td&gt;114&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;query&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rest-xml&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ec2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Unsurprisingly, communicating with JSON is the most popular choice but it is split between &lt;code&gt;json&lt;/code&gt;
and &lt;code&gt;rest-json&lt;/code&gt;.  It would appear that the EC2 service is a one-of-a-kind and has it&amp;rsquo;s own dedicated
protocol, which is probably due to it being one of the oldest AWS services.&lt;/p&gt;
&lt;h3 id=&#34;json-protocol&#34;&gt;JSON Protocol&lt;/h3&gt;
&lt;p&gt;This appears to be the simplest of the protocols. All of the requests are sent to the root path of
the host and a header, &lt;code&gt;x-amz-target&lt;/code&gt;, provides information about which operation to target. All of
the required parameters are provided in the body of the request as JSON.&lt;/p&gt;
&lt;h3 id=&#34;rest-json-protocol&#34;&gt;REST-JSON Protocol&lt;/h3&gt;
&lt;p&gt;Each operation has a different path on the host server. Input parameters can be placed in the URL
path, query string, headers, or request body. The input shape is responsible for encoding which
parameters go where and the request body is formatted with JSON.&lt;/p&gt;
&lt;h3 id=&#34;query-protocol&#34;&gt;Query Protocol&lt;/h3&gt;
&lt;p&gt;The input shape is encoded as &lt;code&gt;x-www-form-urlencoded&lt;/code&gt; and added to the query string of the request.
Nested information of the input shape, such as structures, maps, and lists are encoded are via an
incrementally generated prefix so that the key in the query string could become something like
&lt;code&gt;Foo.bar.member.1=value&lt;/code&gt; for a shape that looks something like &lt;code&gt;{&amp;quot;Foo&amp;quot;: {&amp;quot;bar&amp;quot;: [&amp;quot;value&amp;quot;]}}&lt;/code&gt; in
JSON. Structures are created by &lt;code&gt;prefix.member&lt;/code&gt;, lists are created by &lt;code&gt;prefix.listName.1&lt;/code&gt;, and maps
are created by &lt;code&gt;prefix.mapName.key&lt;/code&gt; and &lt;code&gt;prefix.mapName.value&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;rest-xml-protocol&#34;&gt;REST-XML Protocol&lt;/h3&gt;
&lt;p&gt;The same as rest-json but the request and response bodies are formatted with XML rather than JSON.&lt;/p&gt;
&lt;h3 id=&#34;ec2-protocol&#34;&gt;EC2 Protocol&lt;/h3&gt;
&lt;p&gt;Very similar to the Query protocol; used only on the EC2 service.&lt;/p&gt;
&lt;h2 id=&#34;creating-an-aws-service-code-generator&#34;&gt;Creating an AWS service code generator&lt;/h2&gt;
&lt;p&gt;The python an Ruby SDKs ship with the JSON files and read them every time there is a call to
generate a new client. This is an interesting approach that makes use of metaprogramming in these
languages. I chose instead to use code generation to build the services beforehand. Since Pharo
doesn&amp;rsquo;t separate code and runtime once you create a class it&amp;rsquo;s created and can be accessed in the
image so creating the classes at &amp;ldquo;runtime&amp;rdquo; doesn&amp;rsquo;t really mean the same thing as it does in those
other languages. Furthermore, it&amp;rsquo;s better to generate the classes so they can be imported with
metacello individually if needed. It&amp;rsquo;s very unlikely that you need all 300 odd AWS services in your
image so there is no reason to get all of the data for them. Of course, you are free to use the code
generation package yourself if you have the data files on hand and want to go that way.&lt;/p&gt;
&lt;h3 id=&#34;operations&#34;&gt;Operations&lt;/h3&gt;
&lt;p&gt;I followed the general structure of other SDKs and created a single class for each service.  That
class has a number of messages, one for each of the operations. An operation is simply an API request.&lt;/p&gt;
&lt;p&gt;Here is an example of how an operation is encoded in the JSON data files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;operations&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;#34;CreateAlertManagerDefinition&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;CreateAlertManagerDefinition&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;#34;method&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;#34;requestUri&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/workspaces/{workspaceId}/alertmanager/definition&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;#34;responseCode&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;202&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;CreateAlertManagerDefinitionRequest&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;CreateAlertManagerDefinitionResponse&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;errors&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:[&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ThrottlingException&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ConflictException&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ValidationException&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ResourceNotFoundException&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;AccessDeniedException&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;InternalServerException&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ServiceQuotaExceededException&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;documentation&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;p&amp;gt;Create an alert manager definition.&amp;lt;/p&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;idempotent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The operation name, &lt;code&gt;CreateAlertManagerDefinition&lt;/code&gt;, would get converted to the message
&lt;code&gt;AWSAmp&amp;gt;&amp;gt;createAlertManagerDefinition: aCreateAlertManagerDefinitionRequest&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Due to the way that messages work I chose to model the shapes as objects. In Python SDK, shapes are
not turned into objects but instead the python function calls contain many keyword arguments. This
works well for Python where keyword arguments can be given in any order to a function. In Pharo,
arguments need to be given in order so it becomes quite cumbersome to put in 10 different arguments,
most of which are optional.&lt;/p&gt;
&lt;p&gt;Instead, the operations take a single argument, a request object, that can be serialized.  This is
the same approach that the Go SDK takes.&lt;/p&gt;
&lt;p&gt;The operation above has a templated path on the server: the &lt;code&gt;requestUri&lt;/code&gt; of the operation contains a
parameter, &lt;code&gt;workspaceId&lt;/code&gt; that must be obtained from the input. In this case the
&lt;code&gt;CreateAlertManagerDefinitionRequest&lt;/code&gt; is modeled as an object in Pharo that contains a &lt;code&gt;workspaceId&lt;/code&gt;
accessor.&lt;/p&gt;
&lt;p&gt;The definition of the shapes is also in the JSON data definitions. Below is what the &lt;code&gt;CreateAlertManagerDefinitionRequest&lt;/code&gt;
looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;CreateAlertManagerDefinitionRequest&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;structure&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;required&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:[&lt;/span&gt;
        &lt;span class=&#34;s2&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;s2&#34;&gt;&amp;#34;workspaceId&amp;#34;&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;members&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;#34;clientToken&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;IdempotencyToken&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;documentation&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;p&amp;gt;Optional, unique, case-sensitive, user-provided identifier to ensure the idempotency of the request.&amp;lt;/p&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;idempotencyToken&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;AlertManagerDefinitionData&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;documentation&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;p&amp;gt;The alert manager definition data.&amp;lt;/p&amp;gt;&amp;#34;&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;#34;workspaceId&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:{&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;shape&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;WorkspaceId&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;documentation&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;p&amp;gt;The ID of the workspace in which to create the alert manager definition.&amp;lt;/p&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;location&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;uri&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;nt&#34;&gt;&amp;#34;locationName&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;workspaceId&amp;#34;&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
      &lt;span class=&#34;nt&#34;&gt;&amp;#34;documentation&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;p&amp;gt;Represents the input of a CreateAlertManagerDefinition operation.&amp;lt;/p&amp;gt;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;,&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Shapes also have types, in this case it is a &lt;code&gt;structure&lt;/code&gt; but there are others like &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;,
&lt;code&gt;string&lt;/code&gt;, &lt;code&gt;timestamp&lt;/code&gt;, etc. Structures have a members dictionary which for the smalltalk SDK get
converted into the accessors of the object. You can also see that the members contain some metadata
about where in the request they should be put. The &lt;code&gt;workspaceId&lt;/code&gt; member has a location of the &lt;code&gt;uri&lt;/code&gt;,
whereas the other two members don&amp;rsquo;t have that information (based on the other SDKs this means to put
them in the default location, meaning the body of the request). The members also define their own
shapes creating a recursive descent till the shapes are basic types like &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;using-the-code-generator&#34;&gt;Using the code generator&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34;Load in the code generator group&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nc&#34;&gt;Metacello&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;baseline:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;AWS&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;repository:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;github://ctSkennerton/aws-sdk-smalltalk/pharo-repository&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;load:&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;#(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;Client-Creator&amp;#39;&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;nv&#34;&gt;acc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;AWSClientCreator&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;point the code generator to the directory containing the AWS data files.
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;You will need to bootstrap them from another SDK like botocore.
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;serviceData&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acc&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;findJson:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;/botocore/data&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asFileReference&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;Load in the JSON definition for the Athena service and create the classes&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;athenaDefinition&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; (&lt;span class=&#34;nc&#34;&gt;NeoJSONReader&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;on:&lt;/span&gt; (&lt;span class=&#34;nv&#34;&gt;serviceData&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;at:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;athena&amp;#39;&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;readStream&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;next&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;acc&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;createFromJson:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;athenaDefinition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;install-and-try-it-out&#34;&gt;Install and try it out&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34;Load only the Amp service from the example above.
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;Replace the parameter to load with the services you use&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nc&#34;&gt;Metacello&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;baseline:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;AWS&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;repository:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;github://ctSkennerton/aws-sdk-smalltalk/pharo-repository&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;load:&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;#(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;Amp&amp;#39;&lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;


&lt;span class=&#34;c&#34;&gt;&amp;#34;default parameters to pass to the request. Change to your values&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;workspace&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;CAJK12N&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;COMPLETE&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;Create a new AMP service. Will use your credentials from ~/.aws&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;service&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;AWSAmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;nv&#34;&gt;resp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;service&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;createAlertManagerDefinition:&lt;/span&gt;
    (&lt;span class=&#34;nc&#34;&gt;AWSAmpCreateAlertManagerDefinitionRequest&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;workspaceId:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;workspace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;data:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;data&lt;/span&gt;)&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;project-status-work-still-to-be-done&#34;&gt;Project Status, Work Still to be Done&lt;/h2&gt;
&lt;p&gt;This is still very much a work in progress. So far the class generators cover the JSON and REST-JSON
protocols, which is still 234 different services but lacks some important ones such as ec2, s3, and
SNS. There also isn&amp;rsquo;t any nice parsing of responses from any of the services so the response objects
are basically the raw JSON returned.&lt;/p&gt;
&lt;p&gt;Contributions very welcome, make a pull request on &lt;a href=&#34;https://github.com/ctSkennerton/aws-sdk-smalltalk&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;!---
## Shapes

### Writing Shapes

JSON shapes are easy using NeoJSON mapping. For each shape a `neoJsonMapping` message on the class side of the shape which is recognized by the serializer to convert the custom shapes.

```smalltalk
serviceDAta := AWSClientCreator new findJson: &#39;/tmp/botocore/botocore/data&#39; asFileReference.
sd := serviceDAta collect: [ :a | (NeoJSONReader on: a readStream) next ].

&#34;How unique are shape names across services?&#34;
allShapes := Dictionary new.
sd associationsDo: [ :v |
    (v value at: &#39;shapes&#39;) keysDo: [:s |
        (allShapes at: s ifAbsent: [
            allShapes  at: s put: Set new.
            ]) add: v key ]].

&#34;Here are the duplicated Shapes. There are 5470 of them&#34;
allShapes select: [ :v | v size &gt; 1 ].

&#34;Of the shapes that have the same name, do they have the same definition?&#34;
duplicatedShapeDefinitions := Dictionary new.
(allShapes select: [ :v | v size &gt; 1 ])
	keysAndValuesDo:  [ :shape :services |
		services do: [ :service |
			((duplicatedShapeDefinitions
				at: shape
				ifAbsent: [
                    duplicatedShapeDefinitions at: shape put: OrderedCollection new.]) add: ((sd at: service at: &#39;shapes&#39;)at: shape)) ] ].

&#34;What are the different base types for shapes&#34;
shapeTypes := Bag new.
sd valuesDo: [ :service | (service at: &#39;shapes&#39;) valuesDo: [ :shape | shapeTypes add: (shape at: &#39;type&#39;)] ].
shapeTypes valuesAndCounts
```

This is the general term for the various input and outputs from the operations
There are approximately 46,000 different shapes defined across all services with about 5,000 sharing a name.
The shapes come in a few basic types: structures, lists, maps, strings. Here are all of the options

| type | count |
|------|-------|
| float | 36 |
| blob | 105 |
| double | 211 |
| long | 357 |
| timestamp | 437 |
| map | 612 |
| boolean | 631 |
| integer | 1730 |
| list | 7298 |
| string | 13746 |
| structure | 36981 |


### Mapping the objects to JSON

```smalltalk
t := AWSBatchComputeEnvironmentDetail new type: &#39;container&#39;; computeEnvironmentName: &#39;test&#39;; ecsClusterArn: &#39;arn:::fake&#39;.

bleg := NeoJSONObjectMapping new subjectClass: AWSBatchComputeEnvironmentDetail; mapAccessors: #(type computeEnvironmentName ecsClusterArn); yourself.

String streamContents: [ :stream |
	bleg writeObject: t on: ((NeoJSONWriter on: stream)
	prettyPrint: true)
	].

```
---!&gt;


</description>
		</item>
		<item>
			<title>Dynamic types in Python.</title>
			<link>/2021/11/24/dynamic-types-in-python./</link>
			<pubDate>Wed, 24 Nov 2021 01:45:00 -0800</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2021/11/24/dynamic-types-in-python./</guid>
			<description>&lt;p&gt;I&amp;rsquo;m constantly learning new things about the Python language. I
consider myself a pretty good python programmer but often you never
need to use all of the language features when writing your own code.
For example I&amp;rsquo;ve not used is the class factory pattern using the
&lt;code&gt;type&lt;/code&gt; built in function. I&amp;rsquo;ve been aware of class factories, and
read a few blog posts but never &lt;em&gt;grokked&lt;/em&gt; it, until now.&lt;/p&gt;
&lt;p&gt;A class factory is a function or another class that can create
classes at runtime rather than you writing out the class definition
in code. In other words it&amp;rsquo;s a way to programatically create classes.
Normally when you write python you create classes in your code like
so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__init__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;


&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So above, we define the name of a class, &lt;code&gt;A&lt;/code&gt;, and give it an
initialization method. Then we create and instance of that class,
&lt;code&gt;a&lt;/code&gt;, and print its two instance variables. There is another way to
create this class though using the &lt;a href=&#34;https://docs.python.org/3/library/functions.html#type&#34;&gt;&lt;code&gt;type&lt;/code&gt; function&lt;/a&gt;,
which lets you create types (classes). We could reconstruct the
code above as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;init_func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
    &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
    
&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;__init__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;init_func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The fun bit is the third argument to &lt;code&gt;type&lt;/code&gt; which defines a dictionary
where the keys are the names of methods (and class variables) for
the class. The values of the dictionary are either function names
or values. Note that for &lt;code&gt;init_func&lt;/code&gt; you don&amp;rsquo;t want to add the
parentheses as this will call the function (and give an error). For
me, this also helped illuminate why in python we have to pass &lt;code&gt;self&lt;/code&gt;
as the first argument to a method &amp;ndash; because you can attach on any
old function to a class. It also goes to show that &lt;code&gt;self&lt;/code&gt; is just
a convention. If you were so inclined you could make python look
like another language that uses &lt;code&gt;this&lt;/code&gt; and not &lt;code&gt;self&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Let&amp;#39;s make python look a little more like C++&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# which uses &amp;#34;this&amp;#34; instead of &amp;#34;self&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# Probably don&amp;#39;t want to do this for real as it&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# will really confuse people&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;constructor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Cpp&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;__init__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;constructor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So now lets use this knowledge to make our &amp;ldquo;factory&amp;rdquo;. Take most of
the code above and wrap it in another function. This way you can
pass configuration for your to-be-created class into the outer
function. You can extend this as far as you want and don&amp;rsquo;t have to
make it a function either, you could create a class whose job it
is to create other classes &amp;ndash; a class factory class!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;class_factory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;init_func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
        
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;__init__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;init_func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;class_factory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is all nice and abstract but how and why would you use this?&lt;/p&gt;
&lt;p&gt;Lets have a look at the
&lt;a href=&#34;https://marshmallow.readthedocs.io/en/stable/&#34;&gt;marshmallow&lt;/a&gt; library
which performs object serialization. With marshmallow you can define
incoming data, usually in the form of JSON and convert it to native
python data types (and vice-versa) while validating the data conforms
to a certain schema. Here is the example from their website:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;date&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pprint&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pprint&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;marshmallow&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;ArtistSchema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;AlbumSchema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;release_date&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Date&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;artist&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Nested&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ArtistSchema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;


&lt;span class=&#34;n&#34;&gt;bowie&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;David Bowie&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;album&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;artist&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bowie&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Hunky Dory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;release_date&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;date&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1971&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;17&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;schema&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AlbumSchema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;schema&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dump&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;album&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;pprint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;indent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# { &amp;#39;artist&amp;#39;: {&amp;#39;name&amp;#39;: &amp;#39;David Bowie&amp;#39;},&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#   &amp;#39;release_date&amp;#39;: &amp;#39;1971-12-17&amp;#39;,&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#   &amp;#39;title&amp;#39;: &amp;#39;Hunky Dory&amp;#39;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The key things to note are that you have to create schema classes
that define fields that are of particular types. But what if you
don&amp;rsquo;t know the types beforehand or the types changed outside of the
control of your program? For example, you have a web service that
accepts incoming data, but the input data is user defined (to a
point) and the actual schema of the data are stored outside of your
program. It&amp;rsquo;s not feasible for you to code in a new class in your
web service every time the data changes but you also don&amp;rsquo;t want to
accept any old user data. What you really need is to read in one
of these external schemas to create a validator for the input data
on the fly.&lt;/p&gt;
&lt;p&gt;Class factories to the rescue! Lets see how we can build a marshmallow
schema class from a simple definition stored in JSON as a dictionary
of field names to types.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Dict&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;marshmallow&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;schema_factory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;schema_definition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]):&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        The schema definition is a simple dictionary with the name
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        of the field as the key and a string that defines its type
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        as the value. For example:
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        {
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;            &amp;#39;field1&amp;#39;: &amp;#39;str&amp;#39;,
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;            &amp;#39;field2&amp;#39;: &amp;#39;date&amp;#39;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        }
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;field_type_map&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;str&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;s1&#34;&gt;&amp;#39;date&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Date&lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# add in other types as needed&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;schema_field_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;schema_field_value&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;schema_definition&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# We find the right marshmallow field and initialize it.&lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# Fields then defines the class variables that you would &lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# manually do when defining a marshmallow Schema.&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;schema_field_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;field_type_map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;schema_field_value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]()&lt;/span&gt;
        
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CustomSchema&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
		<item>
			<title>Open Source Tax Software</title>
			<link>/2021/08/30/open-source-tax-software/</link>
			<pubDate>Mon, 30 Aug 2021 18:45:28 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2021/08/30/open-source-tax-software/</guid>
			<description>&lt;p&gt;Filing taxes in America sucks. Your options are to do it by hand, pay someone like Intuit, or
if you are below a certain income threshold get some tax software for free. The kicker is that
free tax software is from Intuit who will try very hard to make sure that you either don&amp;rsquo;t find
it in the first place, or try to get you to pay for it and upsell you on something that should
be free. Check out this &lt;a href=&#34;https://www.propublica.org/article/inside-turbotax-20-year-fight-to-stop-americans-from-filing-their-taxes-for-free&#34;&gt;excellent article&lt;/a&gt; from ProPublica that outlines Intuit&amp;rsquo;s tactics.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve tried to do my taxes by hand and made mistakes that mean I&amp;rsquo;d have to amend my return.
This tax year I was pleasantly surprised to find &lt;a href=&#34;https://excel1040.com&#34;&gt;https://excel1040.com&lt;/a&gt;, which offers
a fairly comprehensive list of federal tax forms. The beauty of excel1040 is that the forms
themselves have been recreated in excel, one form per tab. It&amp;rsquo;s incredibly powerful to see the
forms get filled out automatically as you put in input values from your W-2 or 1099 forms.
And since it&amp;rsquo;s excel you can freely overwrite values if you think they are wrong or add in
new logic if a form isn&amp;rsquo;t implemented yet. The author even says that you can print out the
forms from excel and they&amp;rsquo;ll be accepted, though I didn&amp;rsquo;t try that and instead copied the
values from the spreadsheet onto the pdf forms from the IRS.&lt;/p&gt;
&lt;p&gt;Though I&amp;rsquo;m sure there are unsupported parts of the
tax code in excel1040 it does have a wealth of different forms and the author appears to have
been slowly evolving the complexity of the task over many years.&lt;/p&gt;
&lt;p&gt;The only downside with excel1040 is that it&amp;rsquo;s tricky to understand how all of the formulas
are implemented as there is some complex logic that has to be squeezed into a single line
formula. Here are a couple of examples of what I mean:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;=IF(P74&amp;lt;&amp;gt;&amp;#34;&amp;#34;,P74,IF(NOT(F6251_PIII),&amp;#34;&amp;#34;,IF(AND(SchDTW_Used,NOT(CGTW)),&amp;#39;Sch. D WS&amp;#39;!P87,IF(CGTW,&amp;#39;Line 16 (QDCG Tax)&amp;#39;!J34,0))))
=IF(AM44&amp;lt;&amp;gt;&amp;#34;&amp;#34;,ROUND(AM44,0),IF(OR(AM25,AM29),&amp;#34;&amp;#34;,IF(AL6&amp;lt;&amp;gt;&amp;#34;&amp;#34;,IRA_CONV_YOU,IF(AL7&amp;lt;&amp;gt;&amp;#34;&amp;#34;,IRA_CONV_SPOUSE))))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After I found excel1040, I also discovered &lt;a href=&#34;https://ustaxes.org&#34;&gt;https://ustaxes.org&lt;/a&gt; which is aiming to be a replacement
for paid tax software. It&amp;rsquo;s a website and downloadable application that lets you add in your
income and it does the math and fills in the IRS pdf forms automatically. It is written in
typescript and felt more natural to me (as a programmer) to understand the logic. I&amp;rsquo;ve already
contributed a couple of additions and plan to keep contributing. It doesn&amp;rsquo;t have
as many of the forms implemented as excel1040 but I see it having at least one advantage:
Because it is written in typescript as a custom application, we can take advantage of software
tools like automatic testing, version control, and better structure to the formulas and logic.&lt;/p&gt;
&lt;p&gt;I hope that efforts like excel1040 and ustaxes.org get more popular so that Americans have
additional, free choices when filing their tax.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Using Strings in Pharo Smalltalk</title>
			<link>/2021/07/19/using-strings-in-pharo-smalltalk/</link>
			<pubDate>Mon, 19 Jul 2021 01:20:17 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2021/07/19/using-strings-in-pharo-smalltalk/</guid>
			<description>&lt;p&gt;Smalltalk syntax can be a little confusing coming from other languages. Here I&amp;rsquo;ll show some comparisions
between Python string operations and Smalltalk.&lt;/p&gt;
&lt;h2 id=&#34;substrings--slicing&#34;&gt;Substrings / Slicing&lt;/h2&gt;
&lt;p&gt;Python strings use the slice notation where you can place up to three colon-separated values for the start, stop,
and step. Python strings are 0-indexed and the stop argument is one past the final element that you want.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;abcdefg&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:]&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# bcdefg&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# ab&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# bcdef&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# bcdef&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The slice notation in Python is compact and versatile to be used when getting the beginning, middle, or end
of a string. Smalltalk achieves the same results using a number of different messages that can be a little
confusing when you first get into it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;abcdefg&amp;#39;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;Leave off only the first character&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;allButFirst&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;bcdefg&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;allButFirst with an argument to leave off that many characters&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;allButFirst:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;cdefg&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;There are also the first and last messages that produce the same result
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;as s[1:] or s[:5]. Remember though that Smalltalk&amp;#39;s indexing is 1-based 
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;and inclusive&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;first:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;ab&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;last:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;fg&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;Get the middle of the string&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;copyFrom:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;6&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;bcdef&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;Smalltalk indexing doesn&amp;#39;t have the same trick with negative indexes,
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;instead you need to calculate the size&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;copyFrom:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;formatting&#34;&gt;Formatting&lt;/h2&gt;
&lt;p&gt;Python has extensive string formatting using either the &lt;code&gt;.format()&lt;/code&gt; method of string or using f-strings.
Pharo has a similar &lt;code&gt;format:&lt;/code&gt; message that can be used for inpterpolating other objects in strings.
Each of these objects must have a &lt;code&gt;asString&lt;/code&gt; method for this to work.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34;pass in a collection where values are indexed by number (like Array or OrderedCollection)&amp;#34;&lt;/span&gt;
&lt;span class=&#34;s&#34;&gt;&amp;#39;ab {1} ef {2}&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;format:&lt;/span&gt; {&lt;span class=&#34;s&#34;&gt;&amp;#39;cd&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;gh&amp;#39;&lt;/span&gt;}&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;ab cd ef gh&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;pass in a collection where values are indexed by name&amp;#34;&lt;/span&gt;
&lt;span class=&#34;s&#34;&gt;&amp;#39;ab {one} ef {two}&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;format:&lt;/span&gt; 
    (&lt;span class=&#34;nc&#34;&gt;Dictionary&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;with:&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;#one&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;cd&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;with:&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;#two&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;gh&amp;#39;&lt;/span&gt;)&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;ab cd ef gh&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unlike python there is no format mini-language. Which means that if you want to format things
like numbers in a specific way you need to do that before passing the object to &lt;code&gt;format:&lt;/code&gt;.
Numbers have a basic message &lt;code&gt;printString&lt;/code&gt; that will use the default settings. For very large or
very small numbers it will print in scientific notation.&lt;/p&gt;
&lt;p&gt;There isn&amp;rsquo;t a general number formatter like &lt;code&gt;printf&lt;/code&gt; in C/C++, instead there are messages for each
type of formatting you want on a number. &lt;code&gt;printPaddedWith: aCharacter to: aNumber&lt;/code&gt; is used to
perform left-side padding with a character of your choice. Normally you would choose zero to
mimic the &lt;code&gt;printf&lt;/code&gt; behaviour but you can choose any character you like.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;m&#34;&gt;123&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;printPaddedWith:&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;$0&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;     &lt;span class=&#34;c&#34;&gt;&amp;#34;&amp;#39;00000123&amp;#39;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;123&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;printPaddedWith:&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;$,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;     &lt;span class=&#34;c&#34;&gt;&amp;#34;&amp;#39;,,,,,123&amp;#39;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;123&lt;/span&gt;.&lt;span class=&#34;m&#34;&gt;31&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;printPaddedWith:&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;$0&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;6&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;&amp;#39;000123.31&amp;#39;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;123&lt;/span&gt;.&lt;span class=&#34;m&#34;&gt;31&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;printPaddedWith:&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;$0&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;&amp;#39;123.31&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;printShowingDecimalPlaces: placesDesired&lt;/code&gt; is for controlling the number of decimal places.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;m&#34;&gt;123.31&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;printShowingDecimalPlaces:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;12&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;&amp;#39;123.310000000000&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To combine these with the &lt;code&gt;format:&lt;/code&gt; message you could do something like the following to make
a dynamic array of the values you want:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;{1}&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;format:&lt;/span&gt; {  &lt;span class=&#34;m&#34;&gt;1.123&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;printShowingDecimalPlaces:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There isn&amp;rsquo;t a scientific formatter though, instead the default is to print a number in decimal
format when it&amp;rsquo;s small, and switch to the scientific format as it gets bigger. I found this
a little annoying as I wanted to print numbers in a consistent scientific format no matter their
size.&lt;/p&gt;
&lt;p&gt;There is a package called &lt;a href=&#34;http://ss3.gemstone.com/ss/NumberPrinter/&#34;&gt;NumberPrinter&lt;/a&gt; that has more
versatile printing options, including scientific printing. For example, the default settings with
&lt;code&gt;FloatPrinterScientificFormat&lt;/code&gt; would convert 123.123 to 1.23123e2. But you can change that with
different messages to the number printer.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nv&#34;&gt;rws&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;ReadWriteStream&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;with:&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;fp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;FloatPrinterScientificFormat&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;fp&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;exponentDigitCount:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;fp&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;exponentChar:&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;$E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;fp&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;print:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;123.123&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;on:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rws&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;rws&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;contents&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;1.23123E02&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sadly this is a bit more verbose than python: &lt;code&gt;&#39;{:.5E}&#39;.format(0.09112346) = &#39;9.11235E-02&#39;&lt;/code&gt;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Using Dictionaries in Pharo Smalltalk</title>
			<link>/2020/12/21/using-dictionaries-in-pharo-smalltalk/</link>
			<pubDate>Mon, 21 Dec 2020 13:54:32 -0800</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2020/12/21/using-dictionaries-in-pharo-smalltalk/</guid>
			<description>&lt;p&gt;Starting out with Smalltalk can be a little jarring as it doesn&amp;rsquo;t have the similar syntax as launguages that
are more heavily inspired by C. Dictionaries are one kind of data structure where I noticed this the most so
I put together my notes on using them in Pharo with some comparisons to Python. In many other languages there
is a &lt;em&gt;subscript operator&lt;/em&gt; that allows you to access a value in a dictionary
(and also a position in an array). It&amp;rsquo;s often written &lt;code&gt;dict[key]&lt;/code&gt; to access a value and &lt;code&gt;dict[key]=val&lt;/code&gt; to
set a value to an existing key or add in a new key. Smalltalk doesn&amp;rsquo;t contain
a subscript operator and so interacting with dictionaries requires a slight change
in the mental model to get things done.&lt;/p&gt;
&lt;p&gt;Dictionaries in Pharo are composed of Associations. An Association is a class that holds a single key–value
pair. You can create an Association by sending the &lt;code&gt;-&amp;gt;&lt;/code&gt; binary message to an object (e.g. &lt;code&gt;1 -&amp;gt; 2&lt;/code&gt;). Associations
can be used outside of dictionaries as well, for example the following code snippet creates an Array of Associations:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;{ &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;6&lt;/span&gt; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;initialization&#34;&gt;Initialization&lt;/h2&gt;
&lt;p&gt;You can create a Dictionary from an Array of Associations using the &lt;code&gt;newFrom:&lt;/code&gt; message&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Dictionary&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;newFrom:&lt;/span&gt; { &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;6&lt;/span&gt; }&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or you can achieve the same thing with the &lt;code&gt;at:put:&lt;/code&gt; message:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Dictionary&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt; 
	&lt;span class=&#34;nf&#34;&gt;at:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;put:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; 
	&lt;span class=&#34;nf&#34;&gt;at:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;put:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; 
	&lt;span class=&#34;nf&#34;&gt;at:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;put:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; 
	&lt;span class=&#34;nf&#34;&gt;yourself&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While the &lt;code&gt;newFrom:&lt;/code&gt; message seems intuative to me, the &lt;code&gt;at:put:&lt;/code&gt; way of creating Dictionaries took me
a while to get my head around. First,
notice the semicolons between the successive calls to &lt;code&gt;at:put:&lt;/code&gt;, this is for cascading messages that should
all go to the same &amp;ldquo;receiver&amp;rdquo;, which in this case is the Dictionary object created by &lt;code&gt;new&lt;/code&gt;. What happens
if you don&amp;rsquo;t put in the semicolons? Pharo will get confused and think you are trying to send a single
message called &lt;code&gt;at:put:at:put:at:put:&lt;/code&gt; instead of three separate messages and you&amp;rsquo;ll get an error.
Why is there no semicolon after
&lt;code&gt;new&lt;/code&gt;? So what&amp;rsquo;s happening is that the &lt;code&gt;new&lt;/code&gt; message is creating an instance of the Dictionary class i.e.
a Dictionary object which gets returned from the &lt;code&gt;new&lt;/code&gt; message. The &lt;code&gt;at:put:&lt;/code&gt; messages are then applied to
the return value of &lt;code&gt;new&lt;/code&gt;. If you put a semicolon after &lt;code&gt;new&lt;/code&gt; then all of the subsequent messages will be
sent to what &lt;code&gt;new&lt;/code&gt; was sent to, rather than the result of &lt;code&gt;new&lt;/code&gt;. In other words, &lt;code&gt;at:put:&lt;/code&gt; will be sent to
the Dictionary class and not a Dictionary object (which causes an error). The last bit of the statement, &lt;code&gt;yourself&lt;/code&gt;,
is needed to return the Dictionary object. Without &lt;code&gt;yourself&lt;/code&gt; the return value of the final &lt;code&gt;at:put:&lt;/code&gt; message
is used, which is the value added to the dictionary. If the return value of &lt;code&gt;at:put:&lt;/code&gt; was the dictionary
object then the &lt;code&gt;yourself&lt;/code&gt; message wouldn&amp;rsquo;t be needed at all.&lt;/p&gt;
&lt;h2 id=&#34;accessing-elements&#34;&gt;Accessing elements&lt;/h2&gt;
&lt;p&gt;The basic method of getting values is to use the &lt;code&gt;at:&lt;/code&gt; message:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Dictionary&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;newFrom:&lt;/span&gt; { &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;6&lt;/span&gt; }&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;at:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;&amp;#34;&amp;gt;&amp;gt;&amp;gt; 4&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Just like in Python, if you try to access a key that doesn&amp;rsquo;t exist you&amp;rsquo;ll get an error&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;at:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;   &lt;span class=&#34;c&#34;&gt;&amp;#34;Error KeyNotFound&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;but unlike Python there are multiple ways to avoid this error using variants of the &lt;code&gt;at:&lt;/code&gt; message.
The &lt;code&gt;at:update:initial:&lt;/code&gt; message allows you either update or set a value in a dictionary:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;at:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;update:&lt;/span&gt; [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; ] &lt;span class=&#34;nf&#34;&gt;initial:&lt;/span&gt; [ &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; ]&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which is broadly equivelent to the following Python code&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;KeyError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are many other variants of &lt;code&gt;at:&lt;/code&gt; that modify the behaviour depending on whether the key is present
or not.&lt;/p&gt;
&lt;h2 id=&#34;enumerating&#34;&gt;Enumerating&lt;/h2&gt;
&lt;p&gt;Enumerating in Pharo Smalltalk can also be achieved in multiple ways. The &lt;code&gt;do:&lt;/code&gt; message is available in many
classes for iterating, which for Dictionaries iterates through the values:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;do:&lt;/span&gt; [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Transcript&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;show:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cr&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which is Python would be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;do:&lt;/code&gt; message is an alias for &lt;code&gt;valuesDo:&lt;/code&gt; and there is also a &lt;code&gt;keysDo:&lt;/code&gt; for iterating through the keys
and &lt;code&gt;associationsDo:&lt;/code&gt; for iterating through the key–value pairs. Unlike Python which returns a tuple
of the key and value, in Pharo an Association object is returned. This class responds to the &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt;
messages for accessing each.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;associationsDo:&lt;/span&gt; [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;pair&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Transcript&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;show:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;pair&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;show:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;pair&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cr&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and the Python equivelent:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pair&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pair&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pair&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Despite the differences introduced through the syntax of each language, using dictionaries in Pharo Smalltalk
and Python are basically the same.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Combining properites from different nodes in Gremlin</title>
			<link>/2020/12/13/combining-properites-from-different-nodes-in-gremlin/</link>
			<pubDate>Sun, 13 Dec 2020 15:14:10 -0800</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2020/12/13/combining-properites-from-different-nodes-in-gremlin/</guid>
			<description>&lt;p&gt;One of the key differences between SQL databases and graph databases is the concept of
joining information from different nodes.
In a tinkerpop-enabled graph database nodes have labels that define their type and properties
that are part of that type. It&amp;rsquo;s natural to draw the comparison to a label being an SQL table
and the properties of the nodes being the columns of that table. But trying to extend that
analogy to compare joining in SQL is a little murky. Insead of joining two tables together,
it&amp;rsquo;s better to think about visiting different nodes and
saving their information for later use. In gremlin you can achieve this in a few differnt ways
but the most common is to use the &lt;code&gt;as&lt;/code&gt;-step. The example below shows how to combine information
using the &amp;ldquo;Modern&amp;rdquo; graph that is shipped with tinkerpop. Here there are two types of nodes,
person and software; each have a &amp;ldquo;name&amp;rdquo; property. If you want a mapping of which people created
which software you could do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;hasLabel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;person&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;hasLabel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;software&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;project&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;creator_name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;software_name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)).&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example above the traversal starts with all of the people and saves the information
in the variable, &lt;code&gt;s&lt;/code&gt;, that&amp;rsquo;s what the &lt;code&gt;as(&#39;s&#39;)&lt;/code&gt; is doing. It then travels to the
software nodes, using &lt;code&gt;out(&#39;created&#39;)&lt;/code&gt;. To get the information from both the software
and the person I use the &lt;code&gt;project&lt;/code&gt;-step, which creates a new structure. In this case it will be
a mapping with &lt;code&gt;creator_name&lt;/code&gt; and &lt;code&gt;software_name&lt;/code&gt; as the keys. To get the creator name I use
the &lt;code&gt;select&lt;/code&gt;-step that recalls the information that was stored previously using the variable, &lt;code&gt;s&lt;/code&gt;.
The traversal above will produce a pair-wise mapping like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;{creator_name=marko, software_name=&amp;#34;lop&amp;#34;}
{creator_name=peter, software_name=&amp;#34;lop&amp;#34;}
{creator_name=josh, software_name=&amp;#34;lop&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The other method of combining data is to use the &lt;code&gt;group&lt;/code&gt;-step. In this case the
returned structure will have a mapping based on how you group:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;with the person as the key&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;
&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;hasLabel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;person&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;hasLabel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;software&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;fold&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;or with the software name as the key&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;hasLabel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;software&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;__&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;hasLabel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;person&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;fold&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first query gives you a dictionary where the persons name is the key and the values are
a list of software names created by that person, like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;{
   marko: [lop],
   josh: [lop, ripple],
   peter: [lop]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second version turns it around so that the software is the key and the creators are
the list of values:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;{
    lop: [marko, peter, josh],
    ripple: [josh]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Whether to use the query based on the &lt;code&gt;as&lt;/code&gt;-step or the &lt;code&gt;gorup&lt;/code&gt;-step is dependant on
the structure that you want at the end and the performance. In my experience, grouping
takes longer than using the &lt;code&gt;as&lt;/code&gt;–&lt;code&gt;project&lt;/code&gt; method
and is more flexible too. You can save multiple steps in your traversal with different
variable names and recall them at the appropriate time.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Exploratory data analysis with Pharo Smalltalk</title>
			<link>/2020/12/10/exploratory-data-analysis-with-pharo-smalltalk/</link>
			<pubDate>Thu, 10 Dec 2020 20:19:12 -0800</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2020/12/10/exploratory-data-analysis-with-pharo-smalltalk/</guid>
			<description>&lt;p&gt;The first time I heard about &lt;a href=&#34;https://en.wikipedia.org/wiki/Smalltalk&#34;&gt;Smalltalk&lt;/a&gt;
was reading through the &lt;a href=&#34;https://en.wikipedia.org/wiki/Ruby_(programming_language)&#34;&gt;wikipedia page for Ruby&lt;/a&gt;,
which mentioned it as an influence. At the time I was just a few months into my
transition from a wet-lab biologist into a bioinformatician and trying to decide
between Perl, Python, and Ruby as a scripting language to learn. &lt;label for=&#34;sn-who_won&#34; class=&#34;margin-toggle sidenote-number&#34;&gt;
&lt;/label&gt;
&lt;input type=&#34;checkbox&#34; id=&#34;sn-who_won&#34; class=&#34;margin-toggle&#34; /&gt;
&lt;span class=&#34;sidenote&#34;&gt;
Python became my language of choice after a long battle with Perl
(this was some years ago and Perl was much more relevant).
&lt;/span&gt;

I remember being really intrigued at Smalltalk&amp;rsquo;s syntax and it&amp;rsquo;s pure object-oriented
approach; I was just starting to userstand what these concepts meant but
was already gravitating to OOP. This was a language that seemed very alien to what I was picking up
in C-derived scripting languages. I learned that you made a file with your
program in it and then passed that file as an argument to another program to
interpret it — that&amp;rsquo;s just how programming worked.&lt;/p&gt;
&lt;p&gt;In contrast, instead of code existing in files that are
run by an interpreter or compiled into a binary program, Smalltalk has the concept
of &lt;a href=&#34;https://en.wikipedia.org/wiki/Smalltalk#Image-based_persistence&#34;&gt;image-based persistence&lt;/a&gt;,
which encapsulates the current program state and all of the code into one. Editing your
code is equivelent to changing the program itself rather than a static copy that
gets turned into your program. This is a pretty wild concept and makes programming
much more interactive. An example of how this might streamline your workflow is in
debugging. Often programmers will use a debugger to step through the running code
line by line to see how variable change and find the place where are bug happens.
When the bug is found you then have to go to the line in the source and make the
required change (and either run the program again or re-compile). But with Smalltalk
you&amp;rsquo;re running &amp;ldquo;live&amp;rdquo; code so modifying it during debugging fixes it once. While I
can appreciate this now as a more accomplished programmer, as a newbie I was
utterly confused by it. I never picked it up Smalltalk.&lt;/p&gt;
&lt;p&gt;Recently I was back on wikipedia looking at some other programming language&amp;rsquo;s page
and again there was that smalltalk influence. So I scratched the itch and finally
downloaded Pharo — which seems to be one of the more popular implementations —
and tried out some basic data visualization.&lt;/p&gt;
&lt;p&gt;Pharo is an integrated environment, there isn&amp;rsquo;t really separate source code for writing
programs; they get written one method at a time in the IDE. But there is a playground
feature that allows you to write short scripts and generally play around. The code snippets
I show below are all taken from the playground.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;First we need to install some external packages. Unlike python or R there doesn&amp;rsquo;t seem to
be a single source of packages, instead repositories can be downloaded from URLs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Metacello&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;baseline:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Roassal3Exporters&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;repository:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;github://ObjectProfile/Roassal3Exporters&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;load&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;nc&#34;&gt;Metacello&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;baseline:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;DataFrame&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;repository:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;github://PolyMathOrg/DataFrame/src&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;load&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s look at some penguin data! I&amp;rsquo;m using the &lt;a href=&#34;https://allisonhorst.github.io/palmerpenguins/articles/palmerpenguins.html&#34;&gt;palmerpenduins&lt;/a&gt;
dataset that was built
with R in mind. The &lt;code&gt;DataFrame&lt;/code&gt; package can&amp;rsquo;t load from URLs directly but Pharo provides
some niffty built-in objects that allow us to convert the string URL into a &lt;code&gt;ZnURL&lt;/code&gt; object,
which we can retrieve the contents of (i.e. download).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34;Convert the url string to a Url object and download the contents, passing that into the 
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt; data frame constructor.
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;DataFrame&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;readFromCsv:&lt;/span&gt; 
    &lt;span class=&#34;s&#34;&gt;&amp;#39;https://raw.githubusercontent.com/allisonhorst/palmerpenguins/master/inst/extdata/penguins_raw.csv&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asUrl&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;retrieveContents&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that we can then set up the plot using the various Roassal classes. In the example
below I&amp;rsquo;m plotting the Culmen Length versus the Egg Date columns. It shows off a couple of
tricks I had to learn: first, was how to plot a date on the axis; and second, was how to
deal with &lt;code&gt;NA&lt;/code&gt; values in the data frame.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSChart&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;lineaxes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSScatterPlot&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;Importing the CSV file doesn&amp;#39;t recognize NA so convert them to NaN&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;lineaxes&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;x:&lt;/span&gt; ((&lt;span class=&#34;nv&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;column:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Date Egg&amp;#39;&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;collect:&lt;/span&gt; 
            [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;julianDayNumber&lt;/span&gt; ]) 
         &lt;span class=&#34;nf&#34;&gt;y:&lt;/span&gt; ((&lt;span class=&#34;nv&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;column:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Culmen Length (mm)&amp;#39;&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;collect:&lt;/span&gt; 
            [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;NA&amp;#39;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;ifTrue:&lt;/span&gt; [&lt;span class=&#34;s&#34;&gt;&amp;#39;NaN&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asNumber&lt;/span&gt;] 
                            &lt;span class=&#34;nb&#34;&gt;ifFalse:&lt;/span&gt; [&lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asNumber&lt;/span&gt;] ])&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;addPlot:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;lineaxes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;vticks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSVerticalTick&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
 
&lt;span class=&#34;c&#34;&gt;&amp;#34;Offset controls the horizontal position&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ylabel:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Culmen Length (mm)&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;offset:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;addDecoration:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vticks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;hticks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSHorizontalTick&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;hticks&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;numberOfTicks:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;&amp;#34;Convert the julian day numbers back to Date objects. The asString message will
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;be sent during rendering to make it look pretty&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;hticks&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;labelConversion:&lt;/span&gt; [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Date&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;julianDayNumber:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;x&lt;/span&gt;]&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;useDiagonalLabel&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;addDecoration:&lt;/span&gt;  &lt;span class=&#34;nv&#34;&gt;hticks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;openOnce&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;
    &lt;img src=&#34;/media/2020/12/penguins.png&#34;
         alt=&#34;Basic plot of Penguins with the date as the X-axis&#34; width=&#34;400&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Basic plot of Penguins with the date as the X-axis&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Next I wanted to try and replicate a Facet Grid one of the best features of
&lt;a href=&#34;https://seaborn.pydata.org&#34;&gt;seaborn&lt;/a&gt; and &lt;a href=&#34;https://ggplot2.tidyverse.org&#34;&gt;ggplot2&lt;/a&gt;
for plotting &lt;a href=&#34;https://en.wikipedia.org/wiki/Small_multiple&#34;&gt;small multiples&lt;/a&gt;. I couldn&amp;rsquo;t
find anything built in that would be the equivelent but Roassal has all of the primatives
to make this happen. My solution below is based on the examples in the Roassal package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34;Create a canvas to add our charts to&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSCanvas&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;&amp;#34;First find the unique values in the species column and then loop through the values&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;groups&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; ((&lt;span class=&#34;nv&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;column:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Species&amp;#39;&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;uniqueValues&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;collect:&lt;/span&gt; [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;species&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; 

    &lt;span class=&#34;c&#34;&gt;&amp;#34;Subset the main dataset returning just the rows for the current species&amp;#34;&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;spdf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;select:&lt;/span&gt; [&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;row&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; (&lt;span class=&#34;nv&#34;&gt;row&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;at:&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;#Species&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;species&lt;/span&gt; ]&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
    
    &lt;span class=&#34;c&#34;&gt;&amp;#34;Make a new group that will hold this chart&amp;#34;&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;g&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSGroup&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSChart&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;container:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

    &lt;span class=&#34;c&#34;&gt;&amp;#34;Make a scatterplot&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;nv&#34;&gt;plot&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSScatterPlot&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
    
    &lt;span class=&#34;c&#34;&gt;&amp;#34;Get the x and y values the same as above&amp;#34;&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;plot&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;x:&lt;/span&gt; ((&lt;span class=&#34;nv&#34;&gt;spdf&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;column:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Date Egg&amp;#39;&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;asArray&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;collect:&lt;/span&gt; 
            [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;julianDayNumber&lt;/span&gt; ]) 
         &lt;span class=&#34;nf&#34;&gt;y:&lt;/span&gt; ((&lt;span class=&#34;nv&#34;&gt;spdf&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;column:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Culmen Length (mm)&amp;#39;&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;asArray&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;collect:&lt;/span&gt; 
            [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ifNil:&lt;/span&gt; [&lt;span class=&#34;s&#34;&gt;&amp;#39;NaN&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asNumber&lt;/span&gt;] 
                     &lt;span class=&#34;nf&#34;&gt;ifNotNil:&lt;/span&gt; [&lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asNumber&lt;/span&gt;] ])&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;addPlot:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;plot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;title:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;species&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;chart&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;build&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
    &lt;span class=&#34;c&#34;&gt;&amp;#34;The final statement of a block is returned... so here
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;     we are converting the group object, which holds the chart
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;     into a shape, which is needed to add onto the canvas
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;    &amp;#34;&lt;/span&gt;
	&lt;span class=&#34;nv&#34;&gt;g&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asShape&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
	]&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;nv&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;addAll:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;groups&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;&amp;#34;Layout the three groups horizontally on the canvas&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nc&#34;&gt;RSHorizontalLineLayout&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;on:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shapes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;@&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;RSCanvasController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;openOnce&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;
    &lt;img src=&#34;/media/2020/12/penguins-by-species.png&#34;
         alt=&#34;Split out the into three charts, one for each species&#34; width=&#34;800&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Split out the into three charts, one for each species&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As you can tell from the code samples above there is a lot of boilerplate to set this up.
Roassal isn&amp;rsquo;t a ggplot clone, it&amp;rsquo;s much more low level like base plotting in R or matplotlib.
It&amp;rsquo;s still impressive the variety of things that you can accomplish with it, 2D charts are
just one aspect of Roassal, which is probably why there is a bit more boiler plate than you
might want for just making a chart.&lt;/p&gt;
&lt;p&gt;There is also a bit of roughness to the DataFrame package. The type detection isn&amp;rsquo;t as smart as
in R so columns containing &lt;code&gt;NA&lt;/code&gt; were being left as strings. I fixed this in my examples above wtih:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-smalltalk&#34; data-lang=&#34;smalltalk&#34;&gt;(&lt;span class=&#34;nv&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;column:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Culmen Length (mm)&amp;#39;&lt;/span&gt;) &lt;span class=&#34;nf&#34;&gt;collect:&lt;/span&gt; 
            [ &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;NA&amp;#39;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;ifTrue:&lt;/span&gt; [&lt;span class=&#34;s&#34;&gt;&amp;#39;NaN&amp;#39;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asNumber&lt;/span&gt;] 
                            &lt;span class=&#34;nb&#34;&gt;ifFalse:&lt;/span&gt; [&lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;asNumber&lt;/span&gt;] ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;collect&lt;/code&gt; method returns a new data series where each element has been transformed using the
code block as it&amp;rsquo;s argument. In this can I&amp;rsquo;m checking for &lt;code&gt;NA&lt;/code&gt; and converting to &lt;code&gt;NaN&lt;/code&gt; or the
real number. Similarily, dealing with a date axis involved manually transforming it into a
julian day representation (so basically just a number) and back again for the label. Despite this
I&amp;rsquo;ve come away with a pretty positive opinion of both these packages. The code in DataFrame is easy
to approach and &lt;a href=&#34;https://github.com/PolyMathOrg/DataFrame/pull/134&#34;&gt;I&amp;rsquo;ve already tried to add in a small fix&lt;/a&gt;
that improves the parsing of boolean types from CSV files. I also picked up a bug in the &lt;code&gt;RSScatterPlot&lt;/code&gt;
class that was fixed by the developers almost instantly. It&amp;rsquo;s definitely a small community
but smalltalk makes it easy to investigate and patch bugs on the fly. It&amp;rsquo;s really quite cool
and lends itself to agile development.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to keep using Pharo on the side. For the moment I don&amp;rsquo;t think it could replace python/R
in my professional work but the language is easy and good for quicker analyses.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>A Make for URIs</title>
			<link>/2020/11/16/a-make-for-uris/</link>
			<pubDate>Mon, 16 Nov 2020 18:07:45 -0800</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2020/11/16/a-make-for-uris/</guid>
			<description>&lt;p&gt;&lt;code&gt;Make&lt;/code&gt; has been a one of the key tools in my arsenal for gettings
things done. Although it was developed for compiling code, its
functionality can be generalized to any process that requires files
to be generated based on dependancies.
I recommend you look at these &lt;a href=&#34;https://github.com/vsbuffalo/makefiles-in-bioinfo/blob/master/makefile-slides.pdf&#34;&gt;slides by Vince Buffalo&lt;/a&gt;
as a good introduction to using &lt;code&gt;make&lt;/code&gt; for scientific workflows.
&lt;code&gt;Make&lt;/code&gt; works by creating a
dependancy graph of files and their prerequisites
using the last time the file was
modified as a way to determine if a file needs to be remade.
This general concept is great for
reproducable scientific research or many other repeating
tasks and workflows. However it&amp;rsquo;s not without it&amp;rsquo;s flaws.&lt;/p&gt;
&lt;p&gt;Make&amp;rsquo;s syntax is very obtuse using many shorthand variables like
to describe rules that make it difficult to start using. But
even after leaning its syntax I&amp;rsquo;ve continually found one fatal flaw:
all of the files need to be local, on your current computer.
This makes sense given its original function
of compiling code. However in data analysis and scientific workflows
we often have to interact with remote files on AWS S3 or files that
we download from a web resourse. These files don&amp;rsquo;t have a time stamp
that &lt;code&gt;make&lt;/code&gt; can use and so their presense completely breaks the
dependancy graph.&lt;/p&gt;
&lt;p&gt;There are work arounds of course. I&amp;rsquo;ve used dummy empty files as a
way of keeping track of the last time a URL was downloaded or
just downloaded all of the external files at the beginning and
end of an analysis, which is used in the popular
&lt;a href=&#34;https://drivendata.github.io/cookiecutter-data-science/&#34;&gt;cookiecutter data science template&lt;/a&gt;.
But both of these solutions are brittle and don&amp;rsquo;t really solve the
problem.&lt;/p&gt;
&lt;p&gt;I looked for a URL enabled make, one that could integrate in remote
files to the dependancy graph, but didn&amp;rsquo;t find anything suitable.
So instead I set out to add this functionality to one myself.&lt;/p&gt;
&lt;p&gt;I first looked at the source for &lt;a href=&#34;https://www.gnu.org/software/make/&#34;&gt;GNU make&lt;/a&gt;
however I couldn&amp;rsquo;t understand the &lt;a href=&#34;http://git.savannah.gnu.org/cgit/make.git/tree/&#34;&gt;source code&lt;/a&gt;
so modifying that was out of the question.
Instead I used &lt;code&gt;mk&lt;/code&gt;
as the base for my modifications. &lt;a href=&#34;http://doc.cat-v.org/plan_9/4th_edition/papers/mk&#34;&gt;Mk was originally developed
Plan 9 operating system&lt;/a&gt;
as a re-write of make without many of its annoyances.
I had stumbled upon a simple &lt;a href=&#34;https://github.com/dcjones/mk&#34;&gt;re-implementation of mk in Go by Daniel Jones&lt;/a&gt;
a number of years ago and decided to add remote file support to that.
The changes I describe below are available on &lt;a href=&#34;https://github.com/ctSkennerton/mk&#34;&gt;my fork&lt;/a&gt;
of &lt;code&gt;mk&lt;/code&gt; on Github.&lt;/p&gt;
&lt;p&gt;The goal of my improvemnts was to make the following rule work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span class=&#34;nf&#34;&gt;file.txt.gz&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &amp;#34;&lt;span class=&#34;n&#34;&gt;https&lt;/span&gt;://&lt;span class=&#34;n&#34;&gt;ftp&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;ncbi&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;nlm&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;nih&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;gov&lt;/span&gt;/&lt;span class=&#34;n&#34;&gt;genomes&lt;/span&gt;/&lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;/&lt;span class=&#34;n&#34;&gt;GCF&lt;/span&gt;/001/696/305/&lt;span class=&#34;n&#34;&gt;GCF_&lt;/span&gt;001696305.1&lt;span class=&#34;n&#34;&gt;_UCN&lt;/span&gt;72.1/&lt;span class=&#34;n&#34;&gt;GCF_&lt;/span&gt;001696305.1&lt;span class=&#34;n&#34;&gt;_UCN&lt;/span&gt;72.1&lt;span class=&#34;n&#34;&gt;_feature_count&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;txt&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;gz&lt;/span&gt;&amp;#34;
    curl &lt;span class=&#34;nv&#34;&gt;$prereq&lt;/span&gt; &amp;gt; &lt;span class=&#34;nv&#34;&gt;$target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That is, that &lt;code&gt;mk&lt;/code&gt; would recognise the prerequisite as a URL,
determine if that URL was newer or older than the target and
proceed accordingly.
&lt;label for=&#34;sn-rule_quotes&#34; class=&#34;margin-toggle sidenote-number&#34;&gt;
&lt;/label&gt;
&lt;input type=&#34;checkbox&#34; id=&#34;sn-rule_quotes&#34; class=&#34;margin-toggle&#34; /&gt;
&lt;span class=&#34;sidenote&#34;&gt;
Since there is an extra colon
in the URL we need to protect it with quotes so the mkfile parser
doesn&amp;rsquo;t get confused.
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;The core of &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;mk&lt;/code&gt; is deciding to remake a file based
on whether its prerequisites are newer than it. It does this by
looking at the last modified timestamp of a file. Sure enough inside
&lt;a href=&#34;https://github.com/ctSkennerton/mk/blob/1e476df682360a522b993508429a13ae64d20685/graph.go#L64&#34;&gt;&lt;code&gt;graph.go&lt;/code&gt;&lt;/a&gt;
there was a function &lt;code&gt;updateTimestamp&lt;/code&gt; that gets the
last modified time of a file or sets that the file doesn&amp;rsquo;t exist.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;nx&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Stat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ModTime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
	&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;exists&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
	&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;flags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;nodeFlagProbable&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;PathError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Unix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
		&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;exists&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nf&#34;&gt;mkError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This was the function to modify to look at time stamps of remote
files. To do this we just need to identify files that look like
remote files, i.e. start with http(s):// or s3://. The following
simple modification makes that check and farms out the modification
checking based on if it&amp;rsquo;s a http(s) or s3 remote file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// u is a node in the dependancy graph.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// its name member is the full path of the file
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;strings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;HasPrefix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;s3://&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;strings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;HasPrefix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;https://&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;strings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;HasPrefix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;http://&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;up&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Parse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Fatal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;up&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Scheme&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;up&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Scheme&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;https&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nf&#34;&gt;updateHttpTimestamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;up&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Scheme&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;s3&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;nf&#34;&gt;updateS3Timestamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;up&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The implementation of &lt;code&gt;updateHttpTimestamp&lt;/code&gt; is pretty simple.
A &lt;code&gt;HEAD&lt;/code&gt; request is made to the URL and the &lt;code&gt;Last-Modified&lt;/code&gt;
header is read. If that header is present the time is parsed
and used in the dependancy graph. If the header isn&amp;rsquo;t found
it&amp;rsquo;s assumed that the URL doesn&amp;rsquo;t exist causing it to be remade.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;updateHttpTimestamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;c1&#34;&gt;// get the headers of the URL
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;	&lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Fatal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
	&lt;span class=&#34;nx&#34;&gt;lastModified&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Last-Modified&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;lastModified&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;c1&#34;&gt;// no Last-Modified header so lets assume that it
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;		&lt;span class=&#34;c1&#34;&gt;// doesn&amp;#39;t exist
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;		&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Unix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
		&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;exists&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;nx&#34;&gt;tmptime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Parse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;RFC1123&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;lastModified&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
		&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Fatal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
		&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;tmptime&lt;/span&gt;
		&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;exists&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The implementation for updating an S3 file is similar but uses the
AWS API to get the last modified time.&lt;/p&gt;
&lt;p&gt;And with those small modifications the basic example I showed at the
beginning now works. These modifications can be found in &lt;a href=&#34;https://github.com/ctSkennerton/mk&#34;&gt;my fork&lt;/a&gt;
of &lt;code&gt;mk&lt;/code&gt;, try it out and see how much easier your make-ing becomes!&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Drawing KEGG pathway maps using biopython and matplotlib</title>
			<link>/2020/09/27/drawing-kegg-pathway-maps-using-biopython-and-matplotlib/</link>
			<pubDate>Sun, 27 Sep 2020 22:11:47 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2020/09/27/drawing-kegg-pathway-maps-using-biopython-and-matplotlib/</guid>
			<description>&lt;p&gt;I use &lt;a href=&#34;https://kegg.jp&#34;&gt;KEGG&lt;/a&gt; a lot to understand microbial metabolism.
KEGG is one of the largest resources of enzymes, biochemical
reactions, genes, and molecules, all cross-linked and organized
into what&amp;rsquo;s called metabolic maps. These maps are well-constructed
images of enzymes that functions together for the same overall
purpose like amino acid synthesis, or the metabolism of glucose.
One of the great things about the website is the ability to color
on your data to their metabolic maps. Doing this in bulk though can
be very tedious as you need to view and download individual maps.
Luckily, there is a &lt;a href=&#34;https://nbviewer.jupyter.org/github/widdowquinn/notebooks/blob/master/Biopython_KGML_intro.ipynb&#34;&gt;great tutorial on how to dynamically color KEGG maps&lt;/a&gt;
using biopython that I&amp;rsquo;ve used in the past to create PDF images.&lt;/p&gt;
&lt;p&gt;While this works well, the current biopython graphics module is
based on &lt;a href=&#34;https://www.reportlab.com&#34;&gt;reportlab&lt;/a&gt;, which is a more niche graphics system than
&lt;a href=&#34;https://matplotlib.org&#34;&gt;matplotlib&lt;/a&gt;. This means that the images made in biopython can&amp;rsquo;t
easily be combined with other plots generated with matplotlib and
the biopython implementation of drawing KEGG maps is restricted to
producing PDF documents.&lt;/p&gt;
&lt;p&gt;I was recently working on a project where I needed to combine the
KEGG maps with other types of plots, generated via matplotlib and
didn&amp;rsquo;t want to do it manually in a separate program. Instead I
looked into converting the &lt;code&gt;KEGG_vis&lt;/code&gt; module of biopython from
reportlab to matplotlib. Thankfully, the code is quite short and
self-contained, thus making the conversion process easy.&lt;/p&gt;
&lt;p&gt;Visualizing KEGG data in biopython is driven by KGML, an XML markup
which describes the placement of objects in a pathway map. Biopython
parses this file and draws on the graphics elements based on
this information. Converting the drawing code was pretty
straightforward as many of the concepts between reportlab and
matplotlib are the same. The bulk of the drawing code happens in
the &lt;code&gt;__add_graphics&lt;/code&gt; method, which is responsible for adding in the
lines, circles, and rectangles described in KGML. There is almost
a 1:1 mapping between the reportlab constructs and the equivalent
matplotlib Patch API.  For example drawing a line path in the
original reportlab version looked like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drawing&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beginPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;graphics&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;moveTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;graphics&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lineTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drawing&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drawPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drawing&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setLineWidth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# Return to default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which starts a line at an xy-coordinate and then iterates through all of the remaining point in the path
using the &lt;code&gt;p.lineTo&lt;/code&gt; method. The translation to matplotlib results in very similar code&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;graphics&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;verts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# left, bottom&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;codes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
	&lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MOVETO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;graphics&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
	&lt;span class=&#34;n&#34;&gt;codes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LINETO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
	&lt;span class=&#34;n&#34;&gt;verts&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;verts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;codes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;patch&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;patches&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PathPatch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;    
&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_patch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;patch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;        
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The only major difference was that reportlab seems to use a global
state to keep track of things like the line color and weight;
throughout the original code there are calls to set the font, color,
and line and then return to the original state after certain calls
to draw a graphics object have been made. Alternatively, in matplotlib,
these modifications are passed in directly when creating a new patch
object. Internally I made this change to the API by adding a
&lt;code&gt;**kwargs&lt;/code&gt; argument to the &lt;code&gt;__add_graphics&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# The following code snippet demonstrates the change from reportlab&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# which used calls like setStrokeColor to globally change the state&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# and the new interface which passes these arguments into __add_graphics&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# as kwargs, which will be applied to the matplotlib patches.&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ortholog&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pathway&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;orthologs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ortholog&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;graphics&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
	&lt;span class=&#34;c1&#34;&gt;#self.drawing.setStrokeColor(color_to_reportlab(g.fgcolor))&lt;/span&gt;
	&lt;span class=&#34;c1&#34;&gt;#self.drawing.setFillColor(color_to_reportlab(g.bgcolor))&lt;/span&gt;
	&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;__add_graphics&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bgcolor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fgcolor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This new version of the &lt;code&gt;KEGG_vis&lt;/code&gt; library lives on &lt;a href=&#34;https://github.com/ctSkennerton/biopython/tree/kegg_matplotlib&#34;&gt;my fork of biopython&lt;/a&gt; for now.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Checking back in on CRISPRs</title>
			<link>/2020/09/07/checking-back-in-on-crisprs/</link>
			<pubDate>Mon, 07 Sep 2020 20:34:14 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2020/09/07/checking-back-in-on-crisprs/</guid>
			<description>&lt;p&gt;As part of my PhD thesis I studied an emerging field of bacterial
adaptive immunity, known as &lt;a href=&#34;https://en.wikipedia.org/wiki/CRISPR&#34;&gt;CRISPR&lt;/a&gt;.
At the time I was interested in tracking this type of immune system
in bacterial communities to track co-evolution between bacteria and
their viruses.&lt;label for=&#34;sn-thesis_link&#34; class=&#34;margin-toggle sidenote-number&#34;&gt;
&lt;/label&gt;
&lt;input type=&#34;checkbox&#34; id=&#34;sn-thesis_link&#34; class=&#34;margin-toggle&#34; /&gt;
&lt;span class=&#34;sidenote&#34;&gt;
For anyone interested and brave enough,
&lt;a href=&#34;/media/connor_skennerton_phd_thesis.pdf&#34;&gt;here&lt;/a&gt; is a link to my thesis.
&lt;/span&gt;
  After I finished up
writing, submitting, and ultimately obtaining my PhD I realised that
large portions of the literature review section would never be
published in a scientific journal. I came to the realisation that
if this summary of CRISPR (of which I was very proud of) would ever
be read I needed it to be published in an &amp;ldquo;alternative&amp;rdquo; way.&lt;/p&gt;
&lt;p&gt;That way was Wikipedia and one of my very
first blog posts summarized my method for &lt;a href=&#34;/2014/11/12/uploading-your-theis-literature-review-to-wikipedia/&#34;&gt;turning my literature
review into a Wikipedia article&lt;/a&gt;.  Perhaps my biggest motivation
for contributing to the Wikipedia page was how out of date the page
was. My literature review from my thesis had dozens of references
and was many pages long yet much of this new information wasn&amp;rsquo;t in
Wikipedia at all.&lt;/p&gt;
&lt;p&gt;Towards the very end of my PhD the research community began studying
&lt;a href=&#34;https://en.wikipedia.org/wiki/CRISPR_gene_editing&#34;&gt;CRISPR for gene
editing&lt;/a&gt; which
has resulted in amazing (and &lt;a href=&#34;https://www.nature.com/articles/d41586-019-00673-1&#34;&gt;controversial&lt;/a&gt;)
advances in science using this technique. While CRISPR research
exploded I went off on a different research direction and eventually
left academic research for a position in the biotechnology industry.
Despite not being directly involved with CRISPR research anymore I
still maintain two pieces of software,
&lt;a href=&#34;https://github.com/ctSkennerton/minced&#34;&gt;minced&lt;/a&gt; and
&lt;a href=&#34;https://github.com/ctSkennerton/crass&#34;&gt;crass&lt;/a&gt;, that are designed
to detect CRISPR arrays in either genomes or metagenomes; and
recently I got interested in how the CRISPR page on Wikipedia had
changed since I made my contributions.&lt;/p&gt;
&lt;p&gt;Not surprisingly the number of contributions has increased drastically
from 2014 onwards as CRISPR gene editing got significantly more press
coverage. But what did surprise me was Wikipedia&amp;rsquo;s &lt;a href=&#34;https://xtools.wmflabs.org/articleinfo/en.wikipedia.org/CRISPR&#34;&gt;inbuilt page statistics showing I&amp;rsquo;m the second
highest author&lt;/a&gt; in terms of characters contributed.
It&amp;rsquo;s been years since I contributed so my
assumption was that most of what I wrote would have been edited
away. Seeing my name so prominent really filled me with pride
as this contribution is likely my most read piece of scientific
literature I&amp;rsquo;ve ever made. Digging into the history of the article&amp;rsquo;s revisions it became clear that my
name is still so high on the list due to the
organic nature of Wikipedia article growth. I could see in the history section
that large parts of the CRISPR page had been split off into the
separate &lt;a href=&#34;https://en.wikipedia.org/wiki/CRISPR_gene_editing&#34;&gt;CRISPR gene editing&lt;/a&gt; page,
which is itself a huge page; and the large
&lt;a href=&#34;https://en.wikipedia.org/wiki/Cas9&#34;&gt;cas9&lt;/a&gt; page, which details the
primary enzyme used in CRISPR gene editing. Intuitively this makes sense,
people contribute small amounts to a page that already exists until someone
decides that much of that information is better suited under a different title.&lt;/p&gt;
&lt;p&gt;Some elements for my original contribution are still present including the table of
signature CRISPR genes and a &lt;a href=&#34;https://en.wikipedia.org/wiki/CRISPR#/media/File:The_Stages_of_CRISPR_immunity.svg&#34;&gt;summary figure of the different types
of CRISPR systems&lt;/a&gt;.
Both of these elements are sorely out of date.
I was disappointed to see that the table in particular hadn&amp;rsquo;t been
updated as many of the rows still contained descriptions stating
&amp;ldquo;function unknown&amp;rdquo;. Surely with the increased interest in CRISPR
all of the proteins would have some more information about them.&lt;/p&gt;
&lt;p&gt;Thankfully this assumption was true, much research on CRISPR has
taken place but the information has yet to be disseminated back to
Wikipedia. A quick literature search on Pubmed showed amazing
research on many of the different cas genes. This let me
change a few &amp;ldquo;function unknown&amp;rdquo; rows in the table and let me create a few
new enzyme stubs on Wikipedia for
&lt;a href=&#34;https://en.wikipedia.org/wiki/Cas2&#34;&gt;cas2&lt;/a&gt;,
&lt;a href=&#34;https://en.wikipedia.org/wiki/Cas3&#34;&gt;cas3&lt;/a&gt;, and
&lt;a href=&#34;https://en.wikipedia.org/wiki/Cas4&#34;&gt;cas4&lt;/a&gt;.
I hope that the additional
pages will spurn either myself or others to add information.
&lt;label for=&#34;sn-new_additions&#34; class=&#34;margin-toggle sidenote-number&#34;&gt;
&lt;/label&gt;
&lt;input type=&#34;checkbox&#34; id=&#34;sn-new_additions&#34; class=&#34;margin-toggle&#34; /&gt;
&lt;span class=&#34;sidenote&#34;&gt;
Right after I created the cas3 page another user added in some more information within a day!
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Looking back at this has kindled my own interest in CRISPR again.
A short summary of the information I found and integrated into Wikipedia
while writing this blog post&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;cas4&#34;&gt;cas4&lt;/h3&gt;
&lt;p&gt;Is an endonuclease that works with cas1 and cas2 to generate spacer sequences. It looks for PAM sequences and processes
the spacer before insertion into the CRISPR array.&lt;/p&gt;
&lt;h3 id=&#34;cas5-cas6-cas7&#34;&gt;cas5, cas6, cas7&lt;/h3&gt;
&lt;p&gt;These are essential for generating crispr-RNAs (crRNAs) which are used to target foreign DNA.&lt;/p&gt;
&lt;h3 id=&#34;cas10&#34;&gt;cas10&lt;/h3&gt;
&lt;p&gt;Binds to the 5&amp;rsquo;-end of the CRISPR RNA and promotes the oligomerization of other cas proteins creating the interference
complex that destroys foreign DNA/RNA&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Using Amazon Neptune full text search</title>
			<link>/2020/08/23/using-amazon-neptune-full-text-search/</link>
			<pubDate>Sun, 23 Aug 2020 22:14:10 -0700</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2020/08/23/using-amazon-neptune-full-text-search/</guid>
			<description>&lt;p&gt;I&amp;rsquo;ve been trying out &lt;a href=&#34;https://aws.amazon.com/neptune/&#34;&gt;Amazon Neptune&amp;rsquo;s&lt;/a&gt;
&lt;a href=&#34;https://docs.aws.amazon.com/neptune/latest/userguide/full-text-search.html&#34;&gt;full text search&lt;/a&gt;
feature. Overall it&amp;rsquo;s been a great experience although there are a few caveats when
searching that means that you&amp;rsquo;ll have to craft your queries carefully to make full use
of the feature.&lt;/p&gt;
&lt;p&gt;The tinkerpop standard has &lt;a href=&#34;http://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates&#34;&gt;some text searching features&lt;/a&gt;
however it lacks any advanced features such as searching using regular expressions or even
case-insensitive searching. It&amp;rsquo;s left to different implementations to augment this text
searching capability.&lt;/p&gt;
&lt;p&gt;The developers at Amazon Neptune chose to integrate &lt;a href=&#34;https://www.elastic.co&#34;&gt;Elasticsearch&lt;/a&gt; as
their text searching engine, which offers a rich searching ability.&lt;/p&gt;
&lt;p&gt;The integration between Elasticsearch and Neptune is pretty seamless with clear documentation.
I used AWS&amp;rsquo;s managed elastic search service and I&amp;rsquo;m not sure if an external elasticsearch
setup could work. I already had a Neptune database however to work with elastic search I needed
to turn on the &lt;a href=&#34;https://docs.aws.amazon.com/neptune/latest/userguide/streams.html&#34;&gt;streams feature&lt;/a&gt;
so that data could be replicated from one service to another. After turning on the streams feature
I had to manually reboot my Neptune instances for it to take effect. With the streams feature
turned on I used the &lt;a href=&#34;https://github.com/awslabs/amazon-neptune-tools/tree/master/export-neptune-to-elasticsearch&#34;&gt;export to elasticsearch&lt;/a&gt;
cloudformation template to mirror the data into elastic search. This is a one time operation
as long as the you also use the &lt;a href=&#34;https://docs.aws.amazon.com/neptune/latest/userguide/full-text-search-cfn-create.html&#34;&gt;second cloudformation template&lt;/a&gt;
that uses the Neptune stream to constantly update the elasticsearch index when changes are made
to the neptune database.&lt;/p&gt;
&lt;p&gt;Using the feature with gremlin also works great. When you want to run a query using full text search
you need to add a &lt;code&gt;withSideEffect&lt;/code&gt; step at the begining of the traversal&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;withSideEffect&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Neptune#fts.endpoint&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;ENDPOINT_URL&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then after that you can use full text searching in a &lt;code&gt;has&lt;/code&gt; step. The AWS docs have some
&lt;a href=&#34;https://docs.aws.amazon.com/neptune/latest/userguide/full-text-search-gremlin.html&#34;&gt;good examples&lt;/a&gt;
that show most of the features. Below are a couple of additional observations I made.&lt;/p&gt;
&lt;p&gt;Full text searching is overloaded in the &lt;code&gt;has&lt;/code&gt;-step. You by default you can search in a single property
by using the form &lt;code&gt;has(&amp;quot;&amp;lt;property_key&amp;gt;&amp;quot;, &amp;quot;Neptune#fts &amp;lt;query_string&amp;gt;&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The following searches for all nodes in the graph that have &lt;code&gt;foobar&lt;/code&gt; in their &lt;code&gt;name&lt;/code&gt; property.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;withSideEffect&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Neptune#fts.endpoint&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;ENDPOINT_URL&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;has&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Neptune#fts foobar&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;valueMap&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But you don&amp;rsquo;t have to specify a property. Using a &lt;code&gt;*&lt;/code&gt; character in place of the property key
allows you to search for the term in all of the properties of the nodes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;withSideEffect&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Neptune#fts.endpoint&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;ENDPOINT_URL&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;has&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Neptune#fts foobar&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;valueMap&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using this simple method is an all or one approach, you can&amp;rsquo;t restrict the search to multiple, known
properties. To get this functionality you need to be a little more low-level and use the Lucene syntax,
which the &lt;a href=&#34;https://docs.aws.amazon.com/neptune/latest/userguide/full-text-search-gremlin.html&#34;&gt;docs has some examples of near the end&lt;/a&gt;.
To make use of this you&amp;rsquo;ll need to know a bit about &lt;a href=&#34;https://docs.aws.amazon.com/neptune/latest/userguide/full-text-search-model.html&#34;&gt;how Neptune data is translated into elasticsearch documents&lt;/a&gt;
and also read up on the &lt;a href=&#34;https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html&#34;&gt;query string&lt;/a&gt;
syntax of elastic search.&lt;/p&gt;
&lt;p&gt;Below the &lt;code&gt;has&lt;/code&gt;-step makes use of a full text search looking at both the value of the &lt;code&gt;name&lt;/code&gt; property
and the &lt;code&gt;other_name&lt;/code&gt; property. Due to the way Neptune data is translated into elasticsearch documents
we need to refer to them as &lt;code&gt;predicates.name.value&lt;/code&gt; and &lt;code&gt;predicates.other_name.value&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// note that there is an extra query hint to Neptune to use the query_string syntax for full text search
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;withSideEffect&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Neptune#fts.endpoint&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;ENDPOINT_URL&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;withSideEffect&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Neptune#fts.queryType&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;query_string&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;has&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Neptune#fts predicates.name.value:foo* OR predicates.other_name.value:bar~&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;valueMap&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When looking at the query above you could try to formulate it in a more &amp;ldquo;gremlin&amp;rdquo; way by
having the separate search terms inside a &lt;code&gt;union&lt;/code&gt;-step, like below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;withSideEffect&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Neptune#fts.endpoint&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;ENDPOINT_URL&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;V&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;union&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;has&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Neptune#fts foo*&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;has&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;other_name&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Neptune#fts bar~&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;valueMap&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However in my tests, I&amp;rsquo;ve found this to be very slow in comparison. Although I don&amp;rsquo;t know
why that is we do have to remember that these queries are using two different engines and
any full text search traversal has to go from Neptune through elasticsearch&amp;rsquo;s API and back again;
so it&amp;rsquo;s probably best to make use of as much as the elasticsearch query language can offer
so the two services have to interact the least amount.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>An update on Bioawk</title>
			<link>/2019/10/01/an-update-on-bioawk/</link>
			<pubDate>Tue, 01 Oct 2019 17:26:23 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2019/10/01/an-update-on-bioawk/</guid>
			<description>&lt;p&gt;&lt;a href=&#34;https://github.com/lh3/bioawk&#34;&gt;Bioawk&lt;/a&gt; is a great project started by Heng Li some years ago. The aim was to take the &lt;a href=&#34;https://github.com/onetrueawk/awk&#34;&gt;awk source code&lt;/a&gt; and modify it slightly for use with common biological formats and adding in some new functions. Heng&amp;rsquo;s original doesn&amp;rsquo;t accept too many pull requests so to add in some features, I maintain &lt;a href=&#34;https://github.com/ctSkennerton/bioawk&#34;&gt;my own fork&lt;/a&gt; that has a few improvements.&lt;/p&gt;
&lt;p&gt;Long ago I added in a translate function and recently I added in a function that will take the attribute string from a GFF file and turn it into an awk array. It was possible to split the GFF attribute string in awk itself as the following awk code demonstrates&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;function gffattr(attr, array){
    # split the attribute string into key value pairs
    split(attr, a, &amp;#34;;&amp;#34;)
    for (i in a) {
        # now split out the key and value
        split(a[i], b, &amp;#34;=&amp;#34;)
        for (j in b) {
            array[j] = b[j]
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;but this is a bit clunky and not suited for the kind of one-liner processing that awk excels at. So now with the latest update of my bioawk fork this function is built-in. If you want to filter a GFF on some attribute you can now do something like the following&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;bioawk -c gff &amp;#39;{gffattr($attribute, a); if(a[&amp;#34;some_attr&amp;#34;] == &amp;#34;some_value&amp;#34;) print}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;other-random-updates&#34;&gt;Other random updates&lt;/h2&gt;
&lt;p&gt;The base awk source code has been getting a lot more love recently and my fork has so far merged in all of the upstream updates so there are a few new bug fixes in there.&lt;/p&gt;
&lt;p&gt;Bioawk used to ignore the output field separator when printing the whole record &amp;ndash; this is no longer the case in my fork.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Getting data from NCBI assembly using the accession number only</title>
			<link>/2018/04/10/getting-data-from-ncbi-assembly-using-the-accession-number-only/</link>
			<pubDate>Tue, 10 Apr 2018 23:18:11 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2018/04/10/getting-data-from-ncbi-assembly-using-the-accession-number-only/</guid>
			<description>&lt;p&gt;&lt;a href=&#34;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4702866/&#34;&gt;NCBI&amp;rsquo;s assembly database&lt;/a&gt; is a great one-stop-shop for genomic data and annotations but it&amp;rsquo;s actually kind of difficult to download data if you only know the accession number of an assembly. The documentation says that the assembly database is integrated with &lt;a href=&#34;https://www.ncbi.nlm.nih.gov/books/NBK179288/&#34;&gt;entrez-direct&lt;/a&gt;, a great set of command line utilities for accessing NCBI data from the command line. Most of the databases have an option to download data based on the ID, so I thought that something like the following would work&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;efetch -id GCA_000398025.1 -db assembly -format fasta 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Alas it does not, however the directory structure for the assembly FTP site nicely mirrors the accession numbers so for the example above, the path looks something like this: ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/000/398/025/ Below is a little awk script that I wrote to generate the FTP path and for input into wget. The input for this script is a file containing the accession in the first column and optionally a second column containing the assembly name. The full FTP path contains both of these but we can get around not having the assembly name by using wildcards. Nope, you need both the accession and the assembly name for this snippet to work. But I wrote a more expansive &lt;a href=&#34;https://github.com/ctSkennerton/scriptShed/blob/master/download_ncbi_assembly.py&#34;&gt;script in python that do it with just the accession number&lt;/a&gt;, you should probably use it instead.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;BEGIN{OFS=&amp;#34;/&amp;#34;}
{
  accession = $1;
  joined_acc = accession
  if (NF == 2) {
    joined_acc = joined_acc&amp;#34;_&amp;#34;$2;
  } else {
    joined_acc = joined_acc&amp;#34;*&amp;#34;;
  }
  split($1, a, &amp;#34;_&amp;#34;);
  sub(/\\.[[:digit:]]$/, &amp;#34;&amp;#34;, a[2]);
  gsub(/.{3}/,&amp;#34;&amp;amp;/&amp;#34;, a[2]);
  print accession&amp;#34;\tftp://ftp.ncbi.nlm.nih.gov/genomes/all&amp;#34;,a[1],a[2],joined_acc,joined_acc&amp;#34;_genomic.fna.gz&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
		<item>
			<title>Creating huge metabolic overviews for comparative genomics</title>
			<link>/2017/12/15/creating-huge-metabolic-overviews-for-comparative-genomics/</link>
			<pubDate>Fri, 15 Dec 2017 19:38:46 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2017/12/15/creating-huge-metabolic-overviews-for-comparative-genomics/</guid>
			<description>&lt;p&gt;I love looking at KEGG maps and using them to understand an organisms metabolism but they have their limitations. For starters, you&amp;rsquo;re obviously stuck with how they are drawn, which in most cases includes many variations on a particular pathway. Secondly, the tools for mapping on your own genes to a pathway are limited to one organism at a time. What I really wanted was a way of quickly comparing 10s of genomes across a common set of pathways, in this case amino acid synthesis pathways. Failing to find a suitable way to map on many genomes to KEGGs pathway images, I decided to roll my own. I mixed up manually drawing the pathways and then using code to color in the presence/absence of the reaction in each organism. My solution starts by creating a template svg image in Illustrator. This is the laborious part as I went through and redrew the amino acid pathways using information from both KEGG and MetaCyc. For each enzyme I positioned a grid of boxes, where each box represents an individual genome, that I would eventually color in based on the presence/absence of that reaction in that organism.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;/media/2017/12/template-pathway-part.png&#34;
         alt=&#34;The TCA cycle and parts of the amino acid synthesis pathways. Each reaction is labelled with the EC number and contains a grid of 100 boxes.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;The TCA cycle and parts of the amino acid synthesis pathways. Each reaction is labelled with the EC number and contains a grid of 100 boxes.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Now the trick is to group the parts of the enzyme together and give that group a name in Illustrator. First the grid of 100 boxes was grouped first per row and then I grouped those 10 rows together (this is important and I&amp;rsquo;ll explain why below). And then the boxes, the arrow and the text label all got grouped together. Next name both the larger group and the boxes in Illustrator. You can do this easily by double clicking the group to enter &amp;ldquo;isolation mode&amp;rdquo;, where everything that isn&amp;rsquo;t in the group gets faded, and then changing the name in the layers panel of Illustrator.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;/media/2017/12/enzyme-group-hilight.png&#34;
         alt=&#34;When in isolation mode, the layers panel gives easy access to changing the name of the group. In this case I&amp;amp;rsquo;m calling the group after the EC number.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;When in isolation mode, the layers panel gives easy access to changing the name of the group. In this case I&amp;rsquo;m calling the group after the EC number.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Now comes the critical part in naming - the group containing only the 100 boxes must be start with &amp;ldquo;box-&amp;rdquo; and then what follows will be the identifier that gets used for coloring the boxes.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;/media/2017/12/box-hilight.png&#34;
         alt=&#34;each enzyme has a sub-group containing the matrix of 100 boxes. This group must start with &amp;amp;lsquo;box-&amp;amp;rsquo; and then whatever follows will be used to lookup that reaction for each organism.&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;each enzyme has a sub-group containing the matrix of 100 boxes. This group must start with &amp;lsquo;box-&amp;rsquo; and then whatever follows will be used to lookup that reaction for each organism.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In the case above I&amp;rsquo;m using the EC number again as my identifier. It is whatever is written after the &amp;ldquo;box-&amp;rdquo; in the name of the group that is important. This means that you could use any kind of label in the figure, for simplicity I&amp;rsquo;ve simply kept both the visual label of the enzyme and the name of the group to both use the EC number. Now, the reason why this is important is that we are going to save our figure as an svg file. Svg is an xml based file format, which means that it is simply text and thus is easy to modify using some scripting. Lets have a look at how each enzyme gets encoded in svg:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;/media/2017/12/screen-shot-2017-12-14-at-2-43-24-pm.png&#34;
         alt=&#34;svg of part of one enzyme. the tag in svg is a group. You can see that the names for the whole enzyme and for the group of 100 boxes are retained from Illustrator&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;svg of part of one enzyme. the tag in svg is a group. You can see that the names for the whole enzyme and for the group of 100 boxes are retained from Illustrator&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The names that were given to the groups in Illustrator have been retained in the svg file as the id tags, and it is this text that we&amp;rsquo;ll process using the script. The other thing to note is how the boxes are arranged, in this case as groups of 10 - these are the rows that were made originally.&lt;/p&gt;
&lt;h2 id=&#34;coloring-the-boxes-programmatically&#34;&gt;Coloring the boxes programmatically&lt;/h2&gt;
&lt;p&gt;Now for the scripted part. You&amp;rsquo;ll need the code available &lt;a href=&#34;https://github.com/ctSkennerton/template_metabolic_pathways&#34;&gt;here&lt;/a&gt;, which will color in the boxes based on a couple of text files. Run the script as follows: &lt;code&gt;python color_template.py -e ec_numbers.csv -i template.svg -o colored.svg -c organism_colors.csv&lt;/code&gt; The &lt;em&gt;ec_numbers.csv&lt;/em&gt; file must contain three columns and must have a header row labelled &lt;em&gt;organism&lt;/em&gt;, &lt;em&gt;ec&lt;/em&gt;, &lt;em&gt;lineage&lt;/em&gt;. The &lt;em&gt;organism&lt;/em&gt; column is the name of the organism, the &lt;em&gt;ec&lt;/em&gt; column must contain the identifiers that match up to the names used in the svg file. For example, in the svg file, if there is a box called &amp;ldquo;box-1.1.1.1&amp;rdquo; then the corresponding annotation in the &lt;em&gt;ec&lt;/em&gt; column should be 1.1.1.1. However, there isn&amp;rsquo;t a requirement that this column be EC numbers or even that they are all from the same source. You could combine EC numbers, KO numbers and Pfam families in this column they just have to match what&amp;rsquo;s written in the svg file. The &lt;em&gt;lineage&lt;/em&gt; column should contain information on how to properly order all of the genomes into the 100 boxes. I use the full taxonomy string of the organism to allow for similar organisms to be grouped together. However, this column doesn&amp;rsquo;t require a taxonomy string and is simply used for lexicographic sorting, so you could put anything in there to sort organisms however you want. The &lt;em&gt;organism_colors.csv&lt;/em&gt; file should contain two columns with a header row labelled &lt;em&gt;organism&lt;/em&gt; and &lt;em&gt;color&lt;/em&gt;. The &lt;em&gt;organism&lt;/em&gt; column is the organism name that was used in the &lt;em&gt;ec_numbers.csv&lt;/em&gt; file. The &lt;em&gt;color&lt;/em&gt; column should contain &lt;a href=&#34;https://www.w3schools.com/cssref/css_colors_legal.asp&#34;&gt;a valid css color&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Formatting scientific names in R</title>
			<link>/2017/07/22/formatting-scientific-names-in-r/</link>
			<pubDate>Sat, 22 Jul 2017 17:27:02 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2017/07/22/formatting-scientific-names-in-r/</guid>
			<description>&lt;p&gt;Here is a function that will take a character string in R and return an expression for fancy formatting in plots that properly italicize scientific names. The syntax for doing this is truly quite horrible, but this is how R does it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;scientific_name_formatter&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; 
    &lt;span class=&#34;c1&#34;&gt;# strsplit returns a list but we are passing in only &lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# one name so we just take the first element of the list &lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;words&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;strsplit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fixed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;[[1]]&lt;/span&gt; 
    &lt;span class=&#34;c1&#34;&gt;# some sort of acronym or bin name, leave it alone &lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; 
    &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; 
        &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words[1]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;Candidatus&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; 
            &lt;span class=&#34;c1&#34;&gt;# for candidatus names, only the Candidatus part is italicised # name shortening it for brevity &lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;unitalic&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words[2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;collapse&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;bquote&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;italic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ca.&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;.(unitalic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;grepl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;^\[A-Z\]+$&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;words[1]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; 
            &lt;span class=&#34;c1&#34;&gt;# If the first word is in all caps then it is an abreviation &lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# so we don&amp;#39;t want to italicize that at all &lt;/span&gt;
            &lt;span class=&#34;nf&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; 
            &lt;span class=&#34;c1&#34;&gt;# assume that everything after the second word is strain name # which should not get italicised &lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;unitalic&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words[3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;collapse&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;bquote&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;italic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;.(words[1]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;italic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;.(words[2]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;.(unitalic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; 
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; 
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; 
        &lt;span class=&#34;nf&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;bquote&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;italic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;.(words[1]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;italic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;.(words[2]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))))&lt;/span&gt; 
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; 
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I use it like the following in ggplot by setting the labels in &lt;code&gt;scale_y_discrete&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;scale_y_discrete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;limits&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;organism_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sapply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;organism_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scientific_name_formatter&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
		<item>
			<title>split_by: splitting files on the command line based on content</title>
			<link>/2017/04/09/split_by-splitting-files-on-the-command-line-based-on-content/</link>
			<pubDate>Sun, 09 Apr 2017 08:04:41 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2017/04/09/split_by-splitting-files-on-the-command-line-based-on-content/</guid>
			<description>&lt;p&gt;Unix has so many great ways to perform text manipulation but one niche which hasn&amp;rsquo;t been filled is splitting a tabular file into pieces based on the contents of certain columns. There are two commands, &lt;code&gt;split&lt;/code&gt; and &lt;code&gt;csplit&lt;/code&gt;, that do a similar role. &lt;code&gt;split&lt;/code&gt; can split a file into a certain number of bytes or lines; &lt;code&gt;csplit&lt;/code&gt; uses a regular expression to determine where to split the file. Often for my purposes neither of these tools is a good fit, and what I really want is an equivalent to the &amp;ldquo;group by&amp;rdquo; clause in SQL databases. Group by sorts rows based on certain grouping columns so that you can then perform summaries on that group. &lt;code&gt;split_by&lt;/code&gt; splits out a file based on the grouping columns for further processing on each chunk. For example, say I&amp;rsquo;ve got a delimited text file containing a mix of categorical and numerical data like the following:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;A&lt;/th&gt;
&lt;th&gt;B&lt;/th&gt;
&lt;th&gt;C&lt;/th&gt;
&lt;th&gt;D&lt;/th&gt;
&lt;th&gt;E&lt;/th&gt;
&lt;th&gt;F&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AU&lt;/td&gt;
&lt;td&gt;BR&lt;/td&gt;
&lt;td&gt;447&lt;/td&gt;
&lt;td&gt;223.2&lt;/td&gt;
&lt;td&gt;55958&lt;/td&gt;
&lt;td&gt;US&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AU&lt;/td&gt;
&lt;td&gt;FR&lt;/td&gt;
&lt;td&gt;348&lt;/td&gt;
&lt;td&gt;16.8&lt;/td&gt;
&lt;td&gt;58484&lt;/td&gt;
&lt;td&gt;AU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;US&lt;/td&gt;
&lt;td&gt;UK&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;53.30&lt;/td&gt;
&lt;td&gt;129&lt;/td&gt;
&lt;td&gt;PG&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I want to split this file into smaller files based on what&amp;rsquo;s in column A, which in this example would make two files for the 2 lines containing &amp;ldquo;AU&amp;rdquo; and for the 1 line containing &amp;ldquo;US&amp;rdquo;. Neither, &lt;code&gt;split&lt;/code&gt; or &lt;code&gt;csplit&lt;/code&gt; really handle this case and the only option is to use an &lt;code&gt;awk&lt;/code&gt;, &lt;code&gt;perl&lt;/code&gt; or other script to handle it. (It&amp;rsquo;s also possible to do this in multiple passes with &lt;code&gt;grep&lt;/code&gt;) After writing similar awk one-liners to do this sort of thing I decided to make it a bit more reusable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;#!/usr/bin/awk -f
BEGIN{
    split(cols, group_by, &amp;#34;,&amp;#34;)
    col_sep = &amp;#34;_&amp;#34;
}
{
    if(header == 1 &amp;amp;&amp;amp; NR == 1) {
        next
    }
    out_file = &amp;#34;&amp;#34;
    for(col in group_by) {
        if(col == 1) {
            out_file = group_by[col]
        } else {
            out_file = out_file col_sep group_by[col]
        }
    }
    out_file = (prefix out_file suffix)
    print $0 &amp;gt; out_file
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s the whole program! You can run it like the following, taking advantage of the variables defined in the script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;./split_by -vFS&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;\t&amp;#34;&lt;/span&gt; -vprefix&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;test_split_ -vsuffix&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.tsv&amp;#34;&lt;/span&gt; -vcols&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; -vheader&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; file.tsv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will produce two files on the example above called &amp;ldquo;test_split_AU.tsv&amp;rdquo; and &amp;ldquo;test_split_US.tsv&amp;rdquo;. Only the &lt;em&gt;cols&lt;/em&gt; argument is needed to say which of the columns is used to split on. If you want to split on multiple columns pass a comma separated list &lt;code&gt;-vcols=1,2&lt;/code&gt;. The output file names are generated based on the contents of those columns so if there are any special characters in there that might mess up a file name, you&amp;rsquo;re in trouble. The &lt;em&gt;prefix&lt;/em&gt; and &lt;em&gt;suffix&lt;/em&gt; variables default to nothing but are useful for being able to find the files for later by giving them all a common prefix. The nice thing about this is that all of the &lt;code&gt;awk&lt;/code&gt; variables are still available so changing between a csv and tsv file can be achieved using the &lt;em&gt;FS&lt;/em&gt; parameter on the command line.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Downloading NCBI genomes from a given taxonomy</title>
			<link>/2016/11/20/downloading-ncbi-genomes-from-a-given-taxonomy/</link>
			<pubDate>Sun, 20 Nov 2016 05:18:43 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2016/11/20/downloading-ncbi-genomes-from-a-given-taxonomy/</guid>
			<description>&lt;p&gt;The &lt;a href=&#34;https://www.ncbi.nlm.nih.gov/books/NBK179288/&#34;&gt;Entrez Direct&lt;/a&gt; toolkit is great for programmatic access to all of NCBI&amp;rsquo;s resources. This little snippet below finds all of the refseq representative genomes for a given NCBI taxonomy ID, makes a little summary of the genomes downloaded and uses &lt;code&gt;wget&lt;/code&gt; to download the genbank files from the Assembly FTP. Change the inital query in the first call to &lt;code&gt;esearch&lt;/code&gt; to change what genomes are downloaded.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;esearch -db assembly -query &lt;span class=&#34;s2&#34;&gt;&amp;#34;txid28890[Organism:exp] AND representative [PROP]&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;
 efetch -format docsum &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;
 xtract -pattern DocumentSummary -element 
    AssemblyAccession SpeciesTaxid SpeciesName FtpPath_RefSeq &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;
 sed &lt;span class=&#34;s1&#34;&gt;&amp;#39;s/,.\*//&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;
 sort -k 3,3 &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;
 tee downloaded_genomes.tsv &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;
 cut -f &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;
 sed -e &lt;span class=&#34;s1&#34;&gt;&amp;#39;s/$/\\/\*genomic.gbff.gz/&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;
 wget -i /dev/stdin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
		<item>
			<title>Python ete3: formatting organism names the way I want</title>
			<link>/2016/11/17/python-ete3-formatting-organism-names-the-way-i-want/</link>
			<pubDate>Thu, 17 Nov 2016 00:58:40 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2016/11/17/python-ete3-formatting-organism-names-the-way-i-want/</guid>
			<description>&lt;p&gt;I feel like I&amp;rsquo;m on a life-long quest to make all of my phylogenetic tree figures completely programmatically. The best tool I&amp;rsquo;ve found for making them is the &lt;a href=&#34;http://etetoolkit.org&#34;&gt;ete library&lt;/a&gt; for the python programing language. I&amp;rsquo;ve already figured out how to get &lt;a href=&#34;/2016/07/09/drawing-phylogenetic-trees-connor-style/&#34;&gt;trees drawn in the style that I like&lt;/a&gt; but there was still one thing left to do: making organism names italicize correctly. I work with microorganisms where the convention is for the genus and species names to be italicized but the strain name to be in regular font. For example: &lt;em&gt;Methanoregula formicica&lt;/em&gt; SMSP, DSM 22288. There are exceptions to this as well; if an organism is not in pure culture then the name &lt;em&gt;Candidatus&lt;/em&gt; is prepended and any genus and species names remain in regular format. Unfortunately, ete doesn&amp;rsquo;t have an interface for doing this kind of name formatting, you can either have it italic, bold or regular, but you can&amp;rsquo;t mix and match. Happily though it does contain an interface for dropping down into the lower-level drawing engine (pyQt4), which enables you to do all sorts of custom things. Below is my solution to making fancy formatted organism names. I think it might be a little hacky but seems to work. The organism name should be in the &amp;ldquo;name&amp;rdquo; attribute of the leaf for this to work. (See the example below) Here are the formatting rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If the name has less than 2 words: do nothing. This is to catch internal names or accession numbers that are not valid scientific names&lt;/li&gt;
&lt;li&gt;If the first word of the name is &amp;ldquo;Candidatus&amp;rdquo;: abbreviate it to &amp;ldquo;Ca.&amp;rdquo; and italicize just that part.&lt;/li&gt;
&lt;li&gt;If there are more than 2 words: italicize the first two.&lt;/li&gt;
&lt;li&gt;If there are exactly 2 words: italicize both&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;ete3&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;faces&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TreeStyle&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;PyQt4&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QtCore&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;PyQt4.QtGui&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QGraphicsRectItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QGraphicsSimpleTextItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; \
&lt;span class=&#34;n&#34;&gt;QGraphicsPolygonItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QGraphicsTextItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QPolygonF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; \
     &lt;span class=&#34;n&#34;&gt;QColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QPen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QBrush&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QFont&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;scientific_name_face&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;scientific_name_text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QGraphicsTextItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;words&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# some sort of acronym or bin name, leave it alone&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;elif&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Candidatus&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# for candidatus names, only the Candidatus&lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# part is italicised&lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# name shortening it for brevity&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;i&amp;gt;Ca.&amp;lt;/i&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;extend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:])&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# assume that everything after the&lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# second word is strain name&lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# which should not get italicized&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;extend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;i&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;/i&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;extend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:])&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;extend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;i&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;words&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;/i&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;scientific_name_text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setHtml&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# below is a bit of a hack - I&amp;#39;ve found that the height of the bounding&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# box gives a bit too much padding around the name, so I just minus 10&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# from the height and recenter it. Don&amp;#39;t know whether this is a generally&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# applicable number to use&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QGraphicsRectItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;scientific_name_text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;scientific_name_text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;scientific_name_text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setParentItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;center&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;scientific_name_text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setPos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scientific_name_text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# I don&amp;#39;t want a border around the masterItem&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setPen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QPen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QtCore&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Qt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NoPen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;master_layout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_leaf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;F&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;faces&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DynamicItemFace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scientific_name_face&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;faces&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_face_to_node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# this is fake data to show the rendering&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;populate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;leaves&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_leaves&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# give the leaves some different types of names&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;leaves&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Methanosarcina barkeri&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;leaves&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Candidatus Methanoperedens nitroreducens&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;leaves&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;ANME_bin_23&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;leaves&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Methanosaeta thermophila PT&amp;#39;&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;ts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TreeStyle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ts&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;show_leaf_name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;False&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ts&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;layout_fn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;master_layout&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tree_style&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
		<item>
			<title>My guide to annotating proteins and pathways</title>
			<link>/2016/09/22/my-guide-to-annotating-proteins-and-pathways/</link>
			<pubDate>Thu, 22 Sep 2016 22:14:50 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2016/09/22/my-guide-to-annotating-proteins-and-pathways/</guid>
			<description>&lt;p&gt;So. You&amp;rsquo;ve got yourself a nice new genome sequence and you want to know what kind of metabolism it has. There is a good chance that you have some idea already — you think it&amp;rsquo;s a nitrogen fixer or a sulfate reducer etc. — based on other analyses and now it&amp;rsquo;s time to strengthen your paper with a bit of genomic evidence.&lt;/p&gt;
&lt;h2 id=&#34;getting-an-initial-annotation&#34;&gt;Getting an initial annotation&lt;/h2&gt;
&lt;p&gt;The vast majority of the genes in the genome are going to be hypothetical proteins; of the rest, a sizable chunk are going to be genes with a general sort of annotation like &amp;ldquo;ABC transporter&amp;rdquo; (which says nothing about what it&amp;rsquo;s transporting), and the rest are going to be metabolic genes that you probably care about. The first thing that you want to do is to throw your genome into one of the automatic annotation pipelines (&lt;a href=&#34;https://github.com/tseemann/prokka&#34;&gt;prokka&lt;/a&gt;, &lt;a href=&#34;http://rast.nmpdr.org/&#34;&gt;rast&lt;/a&gt;, &lt;a href=&#34;https://img.jgi.doe.gov/&#34;&gt;img&lt;/a&gt;, &lt;a href=&#34;https://www.ncbi.nlm.nih.gov/genome/annotation_prok/&#34;&gt;ncbi&lt;/a&gt;, &lt;a href=&#34;http://www.genome.jp/tools/kaas/&#34;&gt;kaas&lt;/a&gt;) to get an initial annotation. You can then search through these to look for pathways of interest. However, don&amp;rsquo;t just straight out believe what these pipelines say, they will definitely miss some genes and report annotations that aren&amp;rsquo;t correct, but they are a good start since in most cases you will only be interested in a portion of the genes. The most important thing to remember is to be a scientist. Have a sceptical mindset and interrogate your data. You can&amp;rsquo;t look at every gene (well you can but probably don&amp;rsquo;t have time) so my rule of thumb is that you should manually check all of the genes in all of the pathways that you are going to write about in your paper.&lt;/p&gt;
&lt;h2 id=&#34;my-workflow&#34;&gt;My Workflow&lt;/h2&gt;
&lt;h3 id=&#34;1-compare-the-sequence-of-your-unknown-gene-against-uniprot&#34;&gt;1. Compare the sequence of your unknown gene against Uniprot. &lt;/h3&gt;
&lt;p&gt;You can also use NCBI blast database or IMG or any other database you wish however I like Uniprot because it ranks it annotations with an &lt;a href=&#34;http://www.uniprot.org/help/annotation_score&#34;&gt;overall confidence score&lt;/a&gt;, so you know what kind of experiments has informed the annotation. Uniprot will show some starred proteins that are biochemically verified - this is a good way to figure out if your gene is annotated with the correct function.&lt;/p&gt;
&lt;p&gt;Remember that most genomes are automatically annotated which means that even if all of the top blast hits are annotated as the same thing, it doesn&amp;rsquo;t mean that it&amp;rsquo;s correct. Comparing it against genes that have been biochemically annotated is important.&lt;/p&gt;
&lt;p&gt;Also remember that blast is a local aligner, so don&amp;rsquo;t just look at the e-value, look at the percentage matched of the query (your gene) and the subject (gene in the database). If you have a very long gene and only part of it matches then you should definitely investigate this!&lt;/p&gt;
&lt;h3 id=&#34;2-find-conserved-domains-using-interpro&#34;&gt;2. Find conserved domains using Interpro&lt;/h3&gt;
&lt;p&gt;Sometimes (read: Often) blast matches will not be conclusive or return only a general annotation. In these situations it&amp;rsquo;s best to look at the protein sequence another way. In this case looking at the domains that make up the protein using Interpro may help figure out what it does. This is also a good way to compare your protein to a biochemically analysed protein. I your gene has extra domains, different domains, or fewer domains then it may well be that the blast annotation was incorrect.&lt;/p&gt;
&lt;h3 id=&#34;3-look-at-surrounding-genes&#34;&gt;3. Look at surrounding genes&lt;/h3&gt;
&lt;p&gt;A lot of enzymes are encoded by multiple genes which all exist in one operon. If you want to say that your bug has some enzyme you should make sure that it contains all of the subunits for that enzyme. This can be an essential step where enzymes evolved from a common ancestor such that individual subunits can be difficult to distinguish. &lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3144371/&#34;&gt;A good example here is NADH dehydrogenase and the evolutionarily related hydrogenases&lt;/a&gt;, which can be easily distinguished by the operon structure, but individual subunits often get mis-annotated.&lt;/p&gt;
&lt;h3 id=&#34;4-make-an-alignment-optional&#34;&gt;4. Make an alignment (optional)&lt;/h3&gt;
&lt;p&gt;The last thing you might need to do is to make an alignment to see if your putative enzyme has all (or some of) of the right conserved residues as other biochemically characterised proteins. If the alignment looks terrible then perhaps you&amp;rsquo;ve got something novel.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Messing around with Phyloxml in ete3</title>
			<link>/2016/08/12/messing-around-with-phyloxml-in-ete3/</link>
			<pubDate>Fri, 12 Aug 2016 22:09:04 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2016/08/12/messing-around-with-phyloxml-in-ete3/</guid>
			<description>&lt;p&gt;&lt;a href=&#34;http://etetoolkit.org/&#34;&gt;ete3&lt;/a&gt; has support for &lt;a href=&#34;http://www.phyloxml.org/&#34;&gt;phyloxml&lt;/a&gt; which I use with &lt;a href=&#34;https://sites.google.com/site/cmzmasek/home/software/archaeopteryx&#34;&gt;archaeopteryx&lt;/a&gt; tree viewer for a lot of my day-to-day phylogenetics visualisation. My main reason for using phyloxml is one of convenience as I have a script that will easily add in the proper organism name onto the tree and I think that archaeopteryx is a really good basic tree viewer. I wanted to draw a tree from phyloxml in ete using &lt;a href=&#34;https://connorskennerton.wordpress.com/2016/07/09/drawing-phylogenetic-trees-connor-style/&#34;&gt;my own style&lt;/a&gt; and to have the proper organism name to be rendered. In my phyloxml file I have this coded in as the scientific name for each leaf (see below for phyloxml snippet), so now all I needed to do was make this the node name when rendering the tree.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;clade&amp;gt;&lt;/span&gt; 
  &lt;span class=&#34;nt&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;IMG_2526164742&lt;span class=&#34;nt&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt; 
  &lt;span class=&#34;nt&#34;&gt;&amp;lt;branch_length&amp;gt;&lt;/span&gt;0.19955&lt;span class=&#34;nt&#34;&gt;&amp;lt;/branch_length&amp;gt;&lt;/span&gt; 
  &lt;span class=&#34;nt&#34;&gt;&amp;lt;taxonomy&amp;gt;&lt;/span&gt; 
    &lt;span class=&#34;nt&#34;&gt;&amp;lt;scientific_name&amp;gt;&lt;/span&gt;Desulfobacterium anilini DSM 4660&lt;span class=&#34;nt&#34;&gt;&amp;lt;/scientific_name&amp;gt;&lt;/span&gt; 
  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/taxonomy&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;/clade&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Easy, right? Wrong. I found that the interface for phyloxml was not the same as for newick formatted trees and unfortunately the &lt;a href=&#34;http://etetoolkit.org/docs/latest/reference/reference_phyloxml.html&#34;&gt;documentation for phyloxml in ete3 is a bit lacking&lt;/a&gt; as there wasn&amp;rsquo;t a complete listing of methods for each class. After much messing around, looking at the source code of ete3 and examining python objects using the builtin &lt;a href=&#34;https://docs.python.org/3/library/functions.html#dir&#34;&gt;&lt;code&gt;dir&lt;/code&gt;&lt;/a&gt; function I was able to get what I wanted. turns out that for each node/leaf I needed to access the &lt;code&gt;phyloxml_clade&lt;/code&gt; attribute, which has an attribute taxonomy, which implements an iterable interface (I think it&amp;rsquo;s probably a list), which I could then use to access the scientific name and make the name of the leaf for printing. It&amp;rsquo;s a little convoluted but easy when you know how.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;ete3&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Phyloxml&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;project&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Phyloxml&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# iterate through the trees in the phyloxml file&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tree&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;project&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_phylogeny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# go through the node in the tree&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# assign the node name from the data in the phyloxml file&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;phyloxml_clade&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;taxonomy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_scientific_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;tree&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
		<item>
			<title>Going from a messy supplementary table to good clean data</title>
			<link>/2016/07/11/going-from-a-messy-supplementary-table-to-good-clean-data/</link>
			<pubDate>Mon, 11 Jul 2016 21:00:53 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2016/07/11/going-from-a-messy-supplementary-table-to-good-clean-data/</guid>
			<description>&lt;blockquote&gt;
&lt;p&gt;Bioinformatics&amp;hellip; Or &amp;lsquo;advanced file copying&amp;rsquo; as I like to call it.&lt;/p&gt;
&lt;p&gt;— Nick Loman (@pathogenomenick) &lt;a href=&#34;https://twitter.com/pathogenomenick/status/428616138252353536&#34;&gt;January 29, 2014&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;  Get ready for some advanced file copying! I recently had to clean up some data from the supplementary material from &lt;a href=&#34;http://journal.frontiersin.org/article/10.3389/fmicb.2011.00069/abstract&#34;&gt;Pereira &lt;em&gt;et. al&lt;/em&gt; 2011&lt;/a&gt;, which is a very nice table of manually annotated genes in sulfate reducing bacteria. The only problem is that the table is designed for maximum human readability, which made it a real pain when trying to parse out the data. I decided to use &lt;code&gt;R&lt;/code&gt; and the “&lt;a href=&#34;https://github.com/tidyverse&#34;&gt;tidyverse&lt;/a&gt;” packages to clean up the table to make things work better for downstream analyses. This isn’t part of my normal workflow, I’m more of a python guy, but after doing this analysis in &lt;code&gt;R&lt;/code&gt; I’d have to say that I’m a convert.&lt;/p&gt;
&lt;h4 id=&#34;getting-the-data&#34;&gt;Getting the data&lt;/h4&gt;
&lt;p&gt;Download the supplementary material from the paper linked above, if you want to play along at home. This data is a nicely formatted excel workbook containing eight spreadsheets with the locus identifiers for a number of genes important in suflate reducing prokaryotes. While this data is nice and visually appealing, it is not &lt;a href=&#34;https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html&#34;&gt;tidy&lt;/a&gt; and it’s difficult to get the information I want out of it. I want the locus identifiers for the genes of interest so that I can download them from NCBI and use them as a blast database.&lt;/p&gt;
&lt;h4 id=&#34;cleaning-the-data&#34;&gt;Cleaning the data&lt;/h4&gt;
&lt;p&gt;Some things are just easier to do in excel before tidying the data in &lt;code&gt;R&lt;/code&gt; here is what I did:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;removed the empty columns and rows at the beginning. This actually isn’t difficult to do in &lt;code&gt;R&lt;/code&gt;, but doing this makes inputting the data more painless cause then &lt;code&gt;R&lt;/code&gt; will pick up the column names.&lt;/li&gt;
&lt;li&gt;Remove the rows that contain just the taxonomic information&lt;/li&gt;
&lt;li&gt;For some of the sheets (‘Hases’, for example) I removed rows at the beginning that gave hierarchy to the columns. These are mostly unnecessary and make it difficult to parse the excel sheet, as &lt;code&gt;readxl&lt;/code&gt; does not currently handle merged cells and cause the boundaries of this hierarchy is coded visually using cell boarders in excel.&lt;/li&gt;
&lt;li&gt;For some reason there were single quotation marks in the &lt;em&gt;Archaeoglobus fulgidus&lt;/em&gt; DsrK locus identifiers, which I removed&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Open up an &lt;code&gt;R&lt;/code&gt; session and load the following libraries (assuming that you already have them installed)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tidyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;readxl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stringr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Import the data into &lt;code&gt;R&lt;/code&gt; using &lt;code&gt;readxl&lt;/code&gt;. Creates a list of dataframes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;lapply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;excel_sheets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;~/Downloads/data_sheet_2.xls&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;\&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;read_excel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;~/Downloads/data_sheet_2.xls&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;remove the completely empty rows&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;lapply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;[rowSums&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.na&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ncol&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lets look at what our table looks like (Note the ‘organism’ column is not shown for brevity)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;knitr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;kable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d[[1]][&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;-1&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;locus&lt;/th&gt;
&lt;th&gt;SAT&lt;/th&gt;
&lt;th&gt;AprA&lt;/th&gt;
&lt;th&gt;QmoA&lt;/th&gt;
&lt;th&gt;DsrA&lt;/th&gt;
&lt;th&gt;DsrC&lt;/th&gt;
&lt;th&gt;H-Ppi&lt;/th&gt;
&lt;th&gt;FdxI&lt;/th&gt;
&lt;th&gt;FdxII&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;1667&lt;/td&gt;
&lt;td&gt;1670&lt;/td&gt;
&lt;td&gt;0663&lt;/td&gt;
&lt;td&gt;0423&lt;/td&gt;
&lt;td&gt;2228&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;00427; 1010; 0355; 0923; 2142; 0166; 1700; 0156; 0464&lt;/td&gt;
&lt;td&gt;0167&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arcpr_&lt;/td&gt;
&lt;td&gt;1264&lt;/td&gt;
&lt;td&gt;1261&lt;/td&gt;
&lt;td&gt;1260&lt;/td&gt;
&lt;td&gt;0139&lt;/td&gt;
&lt;td&gt;1726&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;0142; 0625; 0483; 0712; 1058&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cmaq_&lt;/td&gt;
&lt;td&gt;0274&lt;/td&gt;
&lt;td&gt;0273&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;0853&lt;/td&gt;
&lt;td&gt;0856&lt;/td&gt;
&lt;td&gt;0949&lt;/td&gt;
&lt;td&gt;0549; 1711&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DaesDRAFT_&lt;/td&gt;
&lt;td&gt;2031&lt;/td&gt;
&lt;td&gt;2029&lt;/td&gt;
&lt;td&gt;2028&lt;/td&gt;
&lt;td&gt;2438&lt;/td&gt;
&lt;td&gt;0796&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;1729&lt;/td&gt;
&lt;td&gt;0903&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dde_&lt;/td&gt;
&lt;td&gt;2265&lt;/td&gt;
&lt;td&gt;1110&lt;/td&gt;
&lt;td&gt;1111&lt;/td&gt;
&lt;td&gt;0526&lt;/td&gt;
&lt;td&gt;0762&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;3775&lt;/td&gt;
&lt;td&gt;0286&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ddes_&lt;/td&gt;
&lt;td&gt;0454&lt;/td&gt;
&lt;td&gt;2129&lt;/td&gt;
&lt;td&gt;2127&lt;/td&gt;
&lt;td&gt;2275&lt;/td&gt;
&lt;td&gt;1917&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;889&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DMR_&lt;/td&gt;
&lt;td&gt;39470&lt;/td&gt;
&lt;td&gt;05400&lt;/td&gt;
&lt;td&gt;05410&lt;/td&gt;
&lt;td&gt;03600&lt;/td&gt;
&lt;td&gt;15890&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;39570; 18760&lt;/td&gt;
&lt;td&gt;13970&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DESPIG_&lt;/td&gt;
&lt;td&gt;02241&lt;/td&gt;
&lt;td&gt;02773&lt;/td&gt;
&lt;td&gt;02771&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;02353&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;00991&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desal_&lt;/td&gt;
&lt;td&gt;0228&lt;/td&gt;
&lt;td&gt;0230&lt;/td&gt;
&lt;td&gt;0231&lt;/td&gt;
&lt;td&gt;0787&lt;/td&gt;
&lt;td&gt;0984&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;1299&lt;/td&gt;
&lt;td&gt;0241; 2850&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DFW101DRAFT_&lt;/td&gt;
&lt;td&gt;0832&lt;/td&gt;
&lt;td&gt;1162&lt;/td&gt;
&lt;td&gt;1163&lt;/td&gt;
&lt;td&gt;3451&lt;/td&gt;
&lt;td&gt;2958&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;0847&lt;/td&gt;
&lt;td&gt;0729&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DVU&lt;/td&gt;
&lt;td&gt;1295&lt;/td&gt;
&lt;td&gt;0847&lt;/td&gt;
&lt;td&gt;0848&lt;/td&gt;
&lt;td&gt;0402&lt;/td&gt;
&lt;td&gt;2776&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;3276&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dbac_&lt;/td&gt;
&lt;td&gt;3196&lt;/td&gt;
&lt;td&gt;3198&lt;/td&gt;
&lt;td&gt;3199&lt;/td&gt;
&lt;td&gt;0279&lt;/td&gt;
&lt;td&gt;2958&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;0275&lt;/td&gt;
&lt;td&gt;2977&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dalk_&lt;/td&gt;
&lt;td&gt;2445&lt;/td&gt;
&lt;td&gt;1569&lt;/td&gt;
&lt;td&gt;1568&lt;/td&gt;
&lt;td&gt;4301&lt;/td&gt;
&lt;td&gt;4140&lt;/td&gt;
&lt;td&gt;3373&lt;/td&gt;
&lt;td&gt;4380; 2230; 2714&lt;/td&gt;
&lt;td&gt;2374&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HRM2_&lt;/td&gt;
&lt;td&gt;31180&lt;/td&gt;
&lt;td&gt;04510&lt;/td&gt;
&lt;td&gt;04500&lt;/td&gt;
&lt;td&gt;42400&lt;/td&gt;
&lt;td&gt;22050&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;26720; 10680; 01580; 39570&lt;/td&gt;
&lt;td&gt;40690&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dole_&lt;/td&gt;
&lt;td&gt;1002&lt;/td&gt;
&lt;td&gt;0998&lt;/td&gt;
&lt;td&gt;0999&lt;/td&gt;
&lt;td&gt;2669&lt;/td&gt;
&lt;td&gt;0463&lt;/td&gt;
&lt;td&gt;2820&lt;/td&gt;
&lt;td&gt;1168&lt;/td&gt;
&lt;td&gt;2655&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dret_&lt;/td&gt;
&lt;td&gt;1968&lt;/td&gt;
&lt;td&gt;1966&lt;/td&gt;
&lt;td&gt;1965&lt;/td&gt;
&lt;td&gt;0244&lt;/td&gt;
&lt;td&gt;1739&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;0240&lt;/td&gt;
&lt;td&gt;0154; 0169&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DthioDRAFT_&lt;/td&gt;
&lt;td&gt;1410&lt;/td&gt;
&lt;td&gt;1407&lt;/td&gt;
&lt;td&gt;1406&lt;/td&gt;
&lt;td&gt;2272&lt;/td&gt;
&lt;td&gt;2675&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;2268&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DP&lt;/td&gt;
&lt;td&gt;1472&lt;/td&gt;
&lt;td&gt;1105&lt;/td&gt;
&lt;td&gt;1106&lt;/td&gt;
&lt;td&gt;0797&lt;/td&gt;
&lt;td&gt;0997&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;2755; 0775&lt;/td&gt;
&lt;td&gt;1865&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DaAHT2_&lt;/td&gt;
&lt;td&gt;0293&lt;/td&gt;
&lt;td&gt;1471&lt;/td&gt;
&lt;td&gt;1470&lt;/td&gt;
&lt;td&gt;0296&lt;/td&gt;
&lt;td&gt;2041&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;1668&lt;/td&gt;
&lt;td&gt;2532; 2287&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sfum_&lt;/td&gt;
&lt;td&gt;1046&lt;/td&gt;
&lt;td&gt;1048&lt;/td&gt;
&lt;td&gt;1287&lt;/td&gt;
&lt;td&gt;4042&lt;/td&gt;
&lt;td&gt;4045&lt;/td&gt;
&lt;td&gt;3037&lt;/td&gt;
&lt;td&gt;4046&lt;/td&gt;
&lt;td&gt;2933; 3217&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dtox_&lt;/td&gt;
&lt;td&gt;3579&lt;/td&gt;
&lt;td&gt;3577&lt;/td&gt;
&lt;td&gt;3576&lt;/td&gt;
&lt;td&gt;0079&lt;/td&gt;
&lt;td&gt;0077&lt;/td&gt;
&lt;td&gt;3931&lt;/td&gt;
&lt;td&gt;0074; 0532; 1221; 1608; 3208&lt;/td&gt;
&lt;td&gt;1637&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dred_&lt;/td&gt;
&lt;td&gt;0635&lt;/td&gt;
&lt;td&gt;0637&lt;/td&gt;
&lt;td&gt;0638&lt;/td&gt;
&lt;td&gt;3187&lt;/td&gt;
&lt;td&gt;3197&lt;/td&gt;
&lt;td&gt;2985&lt;/td&gt;
&lt;td&gt;3200; 2937; 0466&lt;/td&gt;
&lt;td&gt;2203&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daud_&lt;/td&gt;
&lt;td&gt;1076&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;1884&lt;/td&gt;
&lt;td&gt;2201&lt;/td&gt;
&lt;td&gt;2190&lt;/td&gt;
&lt;td&gt;0308&lt;/td&gt;
&lt;td&gt;2193; 1963&lt;/td&gt;
&lt;td&gt;1080&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adeg_&lt;/td&gt;
&lt;td&gt;1712&lt;/td&gt;
&lt;td&gt;1080&lt;/td&gt;
&lt;td&gt;1079&lt;/td&gt;
&lt;td&gt;2094&lt;/td&gt;
&lt;td&gt;0035&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;0032&lt;/td&gt;
&lt;td&gt;1625&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;THEYE_&lt;/td&gt;
&lt;td&gt;A1835&lt;/td&gt;
&lt;td&gt;A1832&lt;/td&gt;
&lt;td&gt;A1831&lt;/td&gt;
&lt;td&gt;A1994&lt;/td&gt;
&lt;td&gt;A0003&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;A0789&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In the data, the columns for each gene are really values, not variables; they should be converted into individual rows. To do this use the &lt;code&gt;gather&lt;/code&gt; function from &lt;code&gt;tidyr&lt;/code&gt;. Here I specify the name of the new columns &lt;code&gt;gene.identifier&lt;/code&gt; which will contain the name of the gene and &lt;code&gt;locus.identifier&lt;/code&gt; which will contain the information for that gene. I’m also setting &lt;code&gt;na.rm&lt;/code&gt; which will not include genes where it was not found in the organism. After the gather function is applied all of the data frames in the list will have the same columns, which means that they can all be concatenated into one big data frame. To do this I’m using &lt;code&gt;dpylr::bind_rows&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;lapply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;){&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; 
&lt;span class=&#34;nf&#34;&gt;gather&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gene.identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;locus.identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;organism&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;locus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;na.rm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)})&lt;/span&gt; 
&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;bind_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## Warning in rbind_all(x, .id): Unequal factor levels: coercing to character&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;knitr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;kable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d[130&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;140&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;organism&lt;/th&gt;
&lt;th&gt;locus&lt;/th&gt;
&lt;th&gt;gene.identifier&lt;/th&gt;
&lt;th&gt;locus.identifier&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;00427; 1010; 0355; 0923; 2142; 0166; 1700; 0156; 0464&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus profundus&lt;/td&gt;
&lt;td&gt;Arcpr_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0142; 0625; 0483; 0712; 1058&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caldivirga maquilingensis&lt;/td&gt;
&lt;td&gt;Cmaq_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0549; 1711&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio aespoeensis&lt;/td&gt;
&lt;td&gt;DaesDRAFT_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;1729&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio desulfuricans G20&lt;/td&gt;
&lt;td&gt;Dde_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;3775&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio desulfuricans ATCC 27774&lt;/td&gt;
&lt;td&gt;Ddes_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;889&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio magneticus RS-1&lt;/td&gt;
&lt;td&gt;DMR_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;39570; 18760&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio piger&lt;/td&gt;
&lt;td&gt;DESPIG_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;00991&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio salexigens&lt;/td&gt;
&lt;td&gt;Desal_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;1299&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio sp. FW1012B&lt;/td&gt;
&lt;td&gt;DFW101DRAFT_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0847&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio vulgaris Hildenborough&lt;/td&gt;
&lt;td&gt;DVU&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;3276&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The other untidy aspect of the dataset is that there are multiple locus identifiers for some of the genes (presumably cause there are multiple copies in the genome). We next need to split them out into separate observations (rows). The &lt;code&gt;str_split&lt;/code&gt; function from &lt;code&gt;stringr&lt;/code&gt; will split a string based on a regular expression and return a list of values. I then pass this to the &lt;code&gt;unnest&lt;/code&gt; function, which will “flatten” the list into multiple rows as required.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locus.identifier&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; 
&lt;span class=&#34;nf&#34;&gt;str_split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;as.character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locus.identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;; |\\/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; 
&lt;span class=&#34;nf&#34;&gt;unnest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locus.identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;knitr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;kable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d[130&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;140&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;organism&lt;/th&gt;
&lt;th&gt;locus&lt;/th&gt;
&lt;th&gt;gene.identifier&lt;/th&gt;
&lt;th&gt;locus.identifier&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;00427&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;1010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0355&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0923&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;2142&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0166&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;1700&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0156&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0464&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus profundus&lt;/td&gt;
&lt;td&gt;Arcpr_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0142&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus profundus&lt;/td&gt;
&lt;td&gt;Arcpr_&lt;/td&gt;
&lt;td&gt;FdxI&lt;/td&gt;
&lt;td&gt;0625&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Now for the final clean-up. The original data separated the locus prefix and the locus identifier, now I want to combine them back together. To do this I’m going to use a couple of calls to the &lt;code&gt;mutate&lt;/code&gt; function, which modifies a column. First, in the previous command I converted the &lt;code&gt;locus.identifier&lt;/code&gt; column to characters, however this has the unwanted effect of having decimal places in the strings, which I don’t want. Passing the &lt;code&gt;locus.identifier&lt;/code&gt; column to the &lt;code&gt;sub&lt;/code&gt; function will remove the unwanted text. The next &lt;code&gt;mutate&lt;/code&gt; command combines the &lt;code&gt;locus&lt;/code&gt; and &lt;code&gt;locus.identifier&lt;/code&gt; columns into one and finally I select which columns I want in the final data frame using the &lt;code&gt;select&lt;/code&gt; function.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locus.identifier&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; 
&lt;span class=&#34;nf&#34;&gt;sub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;\\.0+&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locus.identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;perl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; 
&lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locus&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locus.identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; 
&lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;organism&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;locus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gene.identifier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;knitr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;kable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d[1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;organism&lt;/th&gt;
&lt;th&gt;locus&lt;/th&gt;
&lt;th&gt;gene.identifier&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus fulgidus&lt;/td&gt;
&lt;td&gt;AF1667&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archaeoglobus profundus&lt;/td&gt;
&lt;td&gt;Arcpr_1264&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caldivirga maquilingensis&lt;/td&gt;
&lt;td&gt;Cmaq_0274&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio aespoeensis&lt;/td&gt;
&lt;td&gt;DaesDRAFT_2031&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio desulfuricans G20&lt;/td&gt;
&lt;td&gt;Dde_2265&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio desulfuricans ATCC 27774&lt;/td&gt;
&lt;td&gt;Ddes_0454&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio magneticus RS-1&lt;/td&gt;
&lt;td&gt;DMR_39470&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio piger&lt;/td&gt;
&lt;td&gt;DESPIG_02241&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio salexigens&lt;/td&gt;
&lt;td&gt;Desal_0228&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desulfovibrio sp. FW1012B&lt;/td&gt;
&lt;td&gt;DFW101DRAFT_0832&lt;/td&gt;
&lt;td&gt;SAT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</description>
		</item>
		<item>
			<title>Drawing Phylogenetic Trees, Connor Style</title>
			<link>/2016/07/09/drawing-phylogenetic-trees-connor-style/</link>
			<pubDate>Sat, 09 Jul 2016 00:23:54 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2016/07/09/drawing-phylogenetic-trees-connor-style/</guid>
			<description>&lt;p&gt;I do a lot of work in phylogenetics, which means that for just about every paper I&amp;rsquo;ve written I&amp;rsquo;ve had at least one figure that is a phylogenetic tree. Making pretty looking trees for a publication is tedious and my previous workflow involved using &lt;a href=&#34;http://arb-home.de&#34;&gt;ARB&lt;/a&gt; for actually drawing the tree and producing an initial file in postscript, and then loading that into Adobe Illustrator to make everything beautiful. The problem with this is that it is not an automated process so any time I need to change the tree I need to redo all of the &amp;lsquo;beautifying&amp;rsquo; manually. Recently I coded up an alternative approach using the excellent &lt;a href=&#34;http://etetoolkit.org/&#34;&gt;ete package&lt;/a&gt; for python to draw trees exactly how I want. One of the nicest things about drawing trees in ARB is that you can collapse clades into wedges. Unfortunately, while ete does allow you to collapse clades it doesn&amp;rsquo;t provide a way to show the collapsed node as a wedge, the only options are a square or a circle. But there is the option to create a &lt;a href=&#34;http://etetoolkit.org/docs/latest/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces&#34;&gt;custom face&lt;/a&gt; which is exactly what I did. Below is a function to create ARB-style wedges:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;polygon_name_face&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width_percent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt; 
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;create a wedge shaped face in the style of ARB 
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        Args: 
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;            width (int): size in pixels for the width of the wedge 
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;            height (int): size in pixels for the height of the wedge 
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;            width_percent (float): change the angle of the point of the wedge. This must be a number between 0 and 1
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;        Returns: QGraphicsRectItem: The Qt graphics item of the polygon 
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt; 
    &lt;span class=&#34;n&#34;&gt;points&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# top left point &lt;/span&gt;
               &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# top right point &lt;/span&gt;
               &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width_percent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# bottom right point &lt;/span&gt;
               &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# bottom left point &lt;/span&gt;
               &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# back to the beginning &lt;/span&gt;
             &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;shape&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QPolygonF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; 
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;points&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;shape&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QtCore&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QPointF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;c1&#34;&gt;## Creates a main master Item that will contain all other elements &lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;## Items can be standard QGraphicsItem &lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QGraphicsRectItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;c1&#34;&gt;# Keep a link within the item to access node info &lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; 
        &lt;span class=&#34;c1&#34;&gt;# I dont want a border around the masterItem &lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setPen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QPen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QtCore&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Qt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NoPen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;polygon&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QGraphicsPolygonItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;c1&#34;&gt;# Make the wedge grey in color &lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;polygon&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setBrush&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QBrush&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;#D3D3D3&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; 
        &lt;span class=&#34;c1&#34;&gt;# Print the name of the node &lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QGraphicsSimpleTextItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setParentItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;polygon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;c1&#34;&gt;# Center text according to masterItem size &lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;tw&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;th&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;center&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setPos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tw&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;center&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;th&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;polygon&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setPos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;boundingRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;masterItem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then to actually use it in a script, set up the tree style. I like to mark internal nodes with bootstrap support &amp;gt;70% with a grey circle and &amp;gt;90% with a black circle as well. Below is the function that I use to add in the groups.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;master_ly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt; 
    &lt;span class=&#34;n&#34;&gt;style&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NodeStyle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; 
    &lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;shape&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;circle&amp;#39;&lt;/span&gt; 
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;support&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;90&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;size&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;fgcolor&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;black&amp;#39;&lt;/span&gt; 
    &lt;span class=&#34;k&#34;&gt;elif&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;support&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;70&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;size&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;fgcolor&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;grey&amp;#39;&lt;/span&gt; 
    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;size&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; 
    
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;grouping_nodes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;draw_descendants&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;False&lt;/span&gt; 
        &lt;span class=&#34;c1&#34;&gt;# Create an ItemFAce. First argument must be the pointer to &lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# the constructor function that returns a QGraphicsItem. It &lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# will be used to draw the Face. Next arguments are arbitrary, &lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# and they will be forwarded to the constructor Face function. &lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# in this case we pass through the width, height, and width_percent for &lt;/span&gt;
        &lt;span class=&#34;c1&#34;&gt;# the wedge. &lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;F&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;faces&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DynamicItemFace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;polygon_name_face&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;faces&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_face_to_node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
        &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally putting it all together&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;ete3&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;faces&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NodeStyle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TreeStyle&lt;/span&gt; 
&lt;span class=&#34;c1&#34;&gt;# We will need to create Qt4 items for making our custom polygon &lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;PyQt4&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QtCore&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;PyQt4.QtGui&lt;/span&gt; 
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;QGraphicsRectItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;QGraphicsSimpleTextItem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; \ 
       &lt;span class=&#34;n&#34;&gt;QGraphicsPolygonItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QPolygonF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QPen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QBrush&lt;/span&gt; 
&lt;span class=&#34;c1&#34;&gt;# Populate this list with the root node of a clade &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# that should be turned into a wedge &lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;grouping_nodes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt; 
&lt;span class=&#34;c1&#34;&gt;# load in your tree from somewhere, this is for fake data &lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;populate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ancestor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_common_ancestor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;aaaaaaaaa&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aaaaaaaaac&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
&lt;span class=&#34;n&#34;&gt;grouping_nodes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ancestor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
&lt;span class=&#34;n&#34;&gt;ts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TreeStyle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; 
&lt;span class=&#34;n&#34;&gt;ts&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;layout_fn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;master_ly&lt;/span&gt; 
&lt;span class=&#34;c1&#34;&gt;# order the subtrees in ascending order &lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ladderize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
&lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tree_style&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are improvements to be made with the way I&amp;rsquo;m drawing the wedge. First, there isn&amp;rsquo;t any border between the top of the wedge and the next leaf — you can see the name &amp;ldquo;aaaaaaaaad&amp;rdquo; is a bit cramped. Second, ARB has a nice feature which changes the wedge dimensions based on the number of grouped leaves which I haven&amp;rsquo;t yet implemented.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/media/2016/07/orig.png&#34; alt=&#34;the original layout&#34;&gt;
&lt;img src=&#34;/media/2016/07/connor_style.png&#34; alt=&#34;connor style&#34;&gt;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Genome Bin Decontamination</title>
			<link>/2015/10/03/genome-bin-decontamination/</link>
			<pubDate>Sat, 03 Oct 2015 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2015/10/03/genome-bin-decontamination/</guid>
			<description>&lt;p&gt;Genome bins comming off automated pipelines can be contaminated
with parts of other genomes. As part of my workflow I use
&lt;a href=&#34;http://genome.cshlp.org/content/early/2015/05/14/gr.186072.114.abstract&#34;&gt;CheckM&lt;/a&gt;
(I&amp;rsquo;m biased since I&amp;rsquo;m a coauthor) to assess the contamination of
genome bins using single-copy marker genes. If you&amp;rsquo;re lucky then
the genome bins that you&amp;rsquo;re interested in will be relatively complete
without much contamination. Unfortunately that isn&amp;rsquo;t always the
case. In this blog post I&amp;rsquo;m going to run through some of the analyses
that I did on a genome bin that was 90% complete but 70% contaminated.
This is exploratory analysis to see if I can manually improve the
bin over what the automated tools can do.&lt;/p&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m not going into details on how I got this bin but briefly I had
three metagenomic samples, named 3730, 5133, and 5579, which were
assembled with
&lt;a href=&#34;http://bioinformatics.oxfordjournals.org/content/31/10/1674.long&#34;&gt;megahit&lt;/a&gt;
and binned using &lt;a href=&#34;https://peerj.com/articles/1165/&#34;&gt;metabat&lt;/a&gt;. I ran
the genome bins from sample 3730 through CheckM. In the below analysis I&amp;rsquo;m going to
try to improve &lt;strong&gt;bin_41&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;analysis&#34;&gt;Analysis&lt;/h2&gt;
&lt;h3 id=&#34;creating-the-input-files&#34;&gt;Creating the input files&lt;/h3&gt;
&lt;p&gt;For starters I want the &lt;code&gt;.depth.txt&lt;/code&gt; file created by metabat, which I copied and renamed &lt;code&gt;3730_coverage.tsv&lt;/code&gt;. Next I created a mapping file for which contigs belonged to which bins. I have the fasta files of all of the bins in a separate directory. To get the mapping of the fasta files I ran the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;grep -oP &lt;span class=&#34;s1&#34;&gt;&amp;#39;(?&amp;lt;=^\&amp;gt;)\S+&amp;#39;&lt;/span&gt; *fa &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;BEGIN{FS=&amp;#34;:&amp;#34;;OFS=&amp;#34;\t&amp;#34;}{print $2,$1}&amp;#39;&lt;/span&gt; &amp;gt; 3730_bin_mapping.tsv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally I wanted to know where all of the multi-copy markers were so I created a file based on the CheckM output, with a bit of reformatting in awk:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;checkm qa -o &lt;span class=&#34;m&#34;&gt;6&lt;/span&gt; ckm_results/lineage.ms ckm_results &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;BEGIN{FS=&amp;#34;\t&amp;#34;;OFS=&amp;#34;,&amp;#34;}{n = split($3,a,&amp;#34;,&amp;#34;);for(i = 1; i &amp;lt;= n; ++i){print $1,$2,a[i]}}&amp;#39;&lt;/span&gt; &amp;gt; 3730_multiple_markers.csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;exploratory-analysis-in-r&#34;&gt;Exploratory analysis in R&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;readr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;duplicated_markers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;3730_multiple_markers.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;coverage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read_tsv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;3730_coverage.tsv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# no header in the file, so give the columns names&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;bin_mapping&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read_tsv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;3730_bin_mapping.tsv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;col_names&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;contigName&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Clean up the dataframes to make the column names consistent and remove a bit of unneeded text. Note that these commands are specific to how files were named on my system, you may not need to do this or change this section to meet your own needs.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;bin_mapping&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gsub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;metabat_binned/final.contigs.fa.metabat_&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin_mapping&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;bin_mapping&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gsub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;\\.fa$&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin_mapping&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;duplicated_markers&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;`Bin Id`&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gsub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;final.contigs.fa.metabat_&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duplicated_markers&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;`Bin Id`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;duplicated_markers&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;`Gene Ids`&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gsub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;_\\d+$&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duplicated_markers&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;`Gene Ids`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;perl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;colnames&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duplicated_markers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;marker&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;contigName&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Create a smaller dataframe of just the binned contigs&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;binned_contigs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;merge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;coverage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;contigName&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are interested in Bin 41, lets get just the data for it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;binned_contigs[binned_contigs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bins_41&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since we have three samples we can look at the coverage of the contigs in each sample as a matrix of 2D&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;pairs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;~&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.3730.bam&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.5133.bam&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.5579.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Comparison of contig coverage between samples&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;3730&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;5133&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;5579&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;/media/bin-decontamination-paired-coverage-1.svg&#34; alt=&#34;plot of chunk bin-decontamination-paired-coverage&#34;&gt;
The majority of the contigs are found in sample 3730 between 10-15x and with very low coverage in sample 5133. Some of the contigs also have some coverage in sample 5579, but most don&amp;rsquo;t. It&amp;rsquo;s tempting to remove all of the contigs that don&amp;rsquo;t fit into the band of coverage, but from this we can&amp;rsquo;t be certain if the duplicated markers are in these outlier contigs.&lt;/p&gt;
&lt;p&gt;Since the coverage of sample 5133 doesn&amp;rsquo;t really factor into things lets look at a single 2D plot of the 3730 coverage and the 5579 coverage. As a coarse approach lets take a look at where all of the contigs with duplicated markers are in this plot. For starters make a new column in the bin_41 dataframe that tells us if the contig contains any duplicated marker.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;n&#34;&gt;bin_41_duplicated_markers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;subset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duplicated_markers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bins_41&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;containsDuplicateMarker&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contigName&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%in%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unique&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_41_duplicated_markers&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contigName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now lets plot the data, changing the color of the points based on the value of the &amp;lsquo;containsDuplicateMarker&amp;rsquo; column&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;plot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.3730.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.5579.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pch&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;19&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;col&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;lightgrey&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xlab&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;3730 coverage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ylab&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;5579 coverage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Contigs containing duplicated markers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;points&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_41[bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;containsDuplicateMarker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.3730.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin_41[bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;containsDuplicateMarker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.5579.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;col&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;
    &lt;img src=&#34;/media/bin-decontamination-all-duplicate-markers-1.svg&#34;/&gt; 
&lt;/figure&gt;
&lt;p&gt;Apart from a couple of outliers, the majority of the contigs that contain multiple markers are in the central mass of contigs. There doesn&amp;rsquo;t appear to be any way to systematically remove a substantial amount of contamination in this genome bin.&lt;/p&gt;
&lt;p&gt;Instead of looking at all contigs that contain any duplicated markers, we can also visualise the positions of contigs for a specific duplicated marker. You can get a list of the markers that are duplicated in the bin by using the unique command. Then create a logical vector of bin_41 of the contigs that contain any of the particular markers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;unique&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_41_duplicated_markers&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;marker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;##   [1] &amp;#34;PF03439.8&amp;#34;  &amp;#34;PF01172.13&amp;#34; &amp;#34;PF00164.20&amp;#34; &amp;#34;PF09173.6&amp;#34;  &amp;#34;PF03874.11&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##   [6] &amp;#34;PF00203.16&amp;#34; &amp;#34;PF00466.15&amp;#34; &amp;#34;PF00416.17&amp;#34; &amp;#34;PF05670.8&amp;#34;  &amp;#34;PF04127.10&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [11] &amp;#34;PF01090.14&amp;#34; &amp;#34;PF01193.19&amp;#34; &amp;#34;PF09249.6&amp;#34;  &amp;#34;PF11987.3&amp;#34;  &amp;#34;PF00298.14&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [16] &amp;#34;PF00252.13&amp;#34; &amp;#34;PF01198.14&amp;#34; &amp;#34;PF01201.17&amp;#34; &amp;#34;PF01351.13&amp;#34; &amp;#34;PF04567.12&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [21] &amp;#34;PF01922.12&amp;#34; &amp;#34;PF01667.12&amp;#34; &amp;#34;PF00398.15&amp;#34; &amp;#34;TIGR03685&amp;#34;  &amp;#34;PF04983.13&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [26] &amp;#34;TIGR03683&amp;#34;  &amp;#34;PF04561.9&amp;#34;  &amp;#34;PF04565.11&amp;#34; &amp;#34;PF04919.7&amp;#34;  &amp;#34;TIGR00425&amp;#34; &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [31] &amp;#34;PF01200.13&amp;#34; &amp;#34;PF07541.7&amp;#34;  &amp;#34;PF00679.19&amp;#34; &amp;#34;PF01194.12&amp;#34; &amp;#34;PF13656.1&amp;#34; &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [36] &amp;#34;PF01015.13&amp;#34; &amp;#34;PF01282.14&amp;#34; &amp;#34;PF01287.15&amp;#34; &amp;#34;PF00276.15&amp;#34; &amp;#34;PF01780.14&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [41] &amp;#34;TIGR00064&amp;#34;  &amp;#34;TIGR00389&amp;#34;  &amp;#34;PF04997.7&amp;#34;  &amp;#34;PF04563.10&amp;#34; &amp;#34;PF03947.13&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [46] &amp;#34;PF01912.13&amp;#34; &amp;#34;PF00181.18&amp;#34; &amp;#34;PF04010.8&amp;#34;  &amp;#34;TIGR00549&amp;#34;  &amp;#34;TIGR01018&amp;#34; &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [51] &amp;#34;PF01157.13&amp;#34; &amp;#34;TIGR00392&amp;#34;  &amp;#34;PF00347.18&amp;#34; &amp;#34;PF00831.18&amp;#34; &amp;#34;TIGR01080&amp;#34; &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [56] &amp;#34;TIGR00408&amp;#34;  &amp;#34;TIGR00270&amp;#34;  &amp;#34;PF08068.7&amp;#34;  &amp;#34;PF00687.16&amp;#34; &amp;#34;PF04560.15&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [61] &amp;#34;PF05000.12&amp;#34; &amp;#34;PF00380.14&amp;#34; &amp;#34;PF00752.12&amp;#34; &amp;#34;PF09377.5&amp;#34;  &amp;#34;TIGR02389&amp;#34; &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [66] &amp;#34;TIGR00419&amp;#34;  &amp;#34;PF01000.21&amp;#34; &amp;#34;PF04566.8&amp;#34;  &amp;#34;PF00562.23&amp;#34; &amp;#34;PF00366.15&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [71] &amp;#34;TIGR00057&amp;#34;  &amp;#34;PF01191.14&amp;#34; &amp;#34;PF00572.13&amp;#34; &amp;#34;PF01981.11&amp;#34; &amp;#34;PF01984.15&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [76] &amp;#34;TIGR03677&amp;#34;  &amp;#34;PF00411.14&amp;#34; &amp;#34;PF01864.12&amp;#34; &amp;#34;PF00238.14&amp;#34; &amp;#34;TIGR03724&amp;#34; &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [81] &amp;#34;PF00177.16&amp;#34; &amp;#34;PF00827.12&amp;#34; &amp;#34;TIGR02338&amp;#34;  &amp;#34;PF01849.13&amp;#34; &amp;#34;TIGR00468&amp;#34; &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [86] &amp;#34;PF01866.12&amp;#34; &amp;#34;PF01982.11&amp;#34; &amp;#34;PF00237.14&amp;#34; &amp;#34;PF03876.12&amp;#34; &amp;#34;PF02978.14&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [91] &amp;#34;TIGR00670&amp;#34;  &amp;#34;PF00623.15&amp;#34; &amp;#34;PF01246.15&amp;#34; &amp;#34;PF00573.17&amp;#34; &amp;#34;PF00189.15&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;##  [96] &amp;#34;TIGR01213&amp;#34;  &amp;#34;TIGR00344&amp;#34;  &amp;#34;PF01868.11&amp;#34; &amp;#34;PF03764.13&amp;#34; &amp;#34;PF00867.13&amp;#34;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;contains_x_marker&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contigName&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%in%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;subset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_41_duplicated_markers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;marker&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;PF01157.13&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contigName&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this vector we can plot the points like we did with the complete set of duplicated markers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;plot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.3730.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin_41&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.5579.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pch&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;19&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;col&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;lightgrey&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Position of contigs with PF01157.13&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xlab&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;3730 coverage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ylab&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;5579 coverage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;points&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin_41[contains_x_marker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.3730.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bin_41[contains_x_marker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final.contigs.5579.bam&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;col&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;
    &lt;img src=&#34;/media/bin-decontamination-single-marker-positions-1.svg&#34;/&gt; 
&lt;/figure&gt;
&lt;p&gt;So now we can see that ther are three contigs containing this marker, one
appears to be an outlier, but the other two contigs have quite similar
coverage profiles&lt;/p&gt;</description>
		</item>
		<item>
			<title>The pace of genome binning from metagenomes</title>
			<link>/2015/06/17/the-pace-of-genome-binning-from-metagenomes/</link>
			<pubDate>Wed, 17 Jun 2015 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2015/06/17/the-pace-of-genome-binning-from-metagenomes/</guid>
			<description>&lt;p&gt;With the pace of science what seemed top stuff three years ago is now an
order of magnitude less than what just got published.&lt;/p&gt;
&lt;p&gt;When I was in my PhD I was working on
&lt;a href=&#34;https://en.wikipedia.org/wiki/Enhanced_biological_phosphorus_removal&#34;&gt;EBPR&lt;/a&gt;
communities using metagenomics to characterize the the microbial and
phage populations. From all of my microbial data I could get about 70 draft
bacterial genomes. At the time (2012) that was pretty huge  considering the first
big paper on genome binning from metagenomes got 49 draft bacteria (&lt;a href=&#34;http://www.sciencemag.org/content/337/6102/1661&#34;&gt;Wrighton et al, 2012&lt;/a&gt;).
The next year a similar study from EBPR recovered 31 draft genome bins
(&lt;a href=&#34;http://www.nature.com/nbt/journal/v31/n6/abs/nbt.2579.html&#34;&gt;Albertsen et al,
2013&lt;/a&gt;). One of the big results
from all this computational effort is that a number of genomes from
&lt;a href=&#34;https://en.wikipedia.org/wiki/Candidate_division&#34;&gt;candidate phyla&lt;/a&gt;. In
2012 I was super excited that I had multiple genomes from
&lt;a href=&#34;https://en.wikipedia.org/wiki/Candidate_division_TM7&#34;&gt;Saccharibacteria&lt;/a&gt;
and
&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id=67820&#34;&gt;Microgenomates&lt;/a&gt;
which at the time had only a few genome representatives. At the time I
thought I had the richest dataset in the world (which I most definitely
did not) now three years later and ~800 genome bins just got published
mostly from those candidate phyla I just mentioned (&lt;a href=&#34;http://www.nature.com/nature/journal/vaop/ncurrent/full/nature14486.html&#34;&gt;Brown et al, 2015&lt;/a&gt;).
It seems like the magnitude of the cutting edge just went up a notch&amp;hellip;&lt;/p&gt;</description>
		</item>
		<item>
			<title>Genome Bin Completeness and Contamination</title>
			<link>/2015/01/29/genome-bin-completeness-and-contamination/</link>
			<pubDate>Thu, 29 Jan 2015 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2015/01/29/genome-bin-completeness-and-contamination/</guid>
			<description>&lt;p&gt;The question that most people ask when looking at a metagenomic draft genome bin
is: should this gene really be there? The answer is that sometimes it&amp;rsquo;s not easy to know&lt;/p&gt;
&lt;p&gt;I spend a lot of my time looking at genome assemblies. They are almost always
from metagenomic data and usually are from some novel phylogenetic lineage
with few (if any) &amp;ldquo;close&amp;rdquo; relatives. Unfortunately the quality of genome
assemblies is such that all of these genomes are in many pieces and due to the
nature of binning, there is always the spectre of some genes not belonging to
the genome that your analyzing. I&amp;rsquo;m currently a middle author on a
&lt;a href=&#34;https://peerj.com/preprints/554/&#34;&gt;paper&lt;/a&gt; that attempts to quantify genome
completeness and contamination using single copy marker genes. The idea is that
there are genes that are always found in a single copy per genome, therefore
if you find them in multiple copies then you&amp;rsquo;ve got some contamination from
other sources. This is great in principle but the number of single-copy genes
is going to be very small for a large set of genomes, for example there are
about 100 of these genes that are common for all bacteria. Assuming that some
bacterial genome has approximately 3000 genes, then looking at only 100 of them
is about 3% of the gene content. That&amp;rsquo;s quite a small percentage to be making
big statements on how good or bad a genome is.&lt;/p&gt;
&lt;p&gt;So here is a question that one of my colleagues posed in a group meeting: if a genome has 10%
contamination does that mean that 1 in 10 genes shouldn&amp;rsquo;t be there?&lt;/p&gt;
&lt;p&gt;My answer is: of course not, it means that 1 in 10 of the marker genes are in
multiple copies. But it does get me thinking, how can we tell that 10% of all
genes in the genome aren&amp;rsquo;t from contamination?&lt;/p&gt;
&lt;p&gt;One of the observations with
single-copy marker genes is that many of them are
co-located such that getting one erroneous contig can disproportionatly increase
contamination. Similarly all of the genes of a contig are either correctly or
incorrectly binned, rather than every 10th gene in some contig being from a
different genome. If we were to assume a perfect situation where every contaminating
contig contained at least one marker gene then the real value of contamination would be
the total number of genes on those contaminating contigs divided by the total number
of genes in the genome bin. The &amp;ldquo;real&amp;rdquo; contamination percent then becomes more
about the size of the contigs rather than the number of marker genes. This is
easy in theory but hard to determine in practice since you need to know which
copy of the marker gene is the contaminant and which is legit.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s easy to remove
contigs with extra marker genes to lower the contamination numbers but what about
short contigs that contain no markers? I don&amp;rsquo;t think there is a perfect way
to tell if they belong to a genome or not but one approach has been to look for
paired reads that link these contigs to larger ones in the assembly even if they
are not contiguous. Here again there are questions raised, if there are reads that
link the contig to the bigger assembly why is it separate, why hasn&amp;rsquo;t the assembler
joined the contigs together? The magic behind genome assemblers creates many
interesting outcomes that I can never explain and as such there is no general rule
for believing paired-end links or not. Honestly, I usually go with my gut
(very unscientific) and generally only bother to go further in depth if there are
genes that are important to the story I&amp;rsquo;m trying to write.&lt;/p&gt;
&lt;p&gt;The golden rule of interpreting genome bin assemblies is that
the bigger the contig the more confident that you become in assigning
them to a draft genome.
(Of course the answer is just getting a better assembly :P).&lt;/p&gt;
&lt;p&gt;With these observations and caveats in mind, what value is there in placing a
percent completeness or contamination based on marker genes if it doesn&amp;rsquo;t really
relate to the total gene content?&lt;/p&gt;
&lt;p&gt;I think there is a lot of value but not when the numbers are taken literally.
Marker genes are an approximation and
a way of sorting genomes that are worth a closer look. From experience I can
tell you that a genome that is
&amp;ldquo;90% complete, 5% contamination&amp;rdquo; looks a lot better than one that is
&amp;ldquo;50% complete, 30% contamination&amp;rdquo;. I take these numbers to be a relative score
along with other factors like the total number of contigs (less is better) and the
total number of bases (does it look like it&amp;rsquo;s about the size of a whole genome)
to point me in the right direction of what I should work on first.&lt;/p&gt;</description>
		</item>
		<item>
			<title>Uploading your Theis Literature Review to Wikipedia</title>
			<link>/2014/11/12/uploading-your-theis-literature-review-to-wikipedia/</link>
			<pubDate>Wed, 12 Nov 2014 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2014/11/12/uploading-your-theis-literature-review-to-wikipedia/</guid>
			<description>&lt;p&gt;Every PhD student can contribute to open science by uploading their thesis
literature review onto Wikipedia!&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;My thesis was entitled &amp;ldquo;Phage-host evolution in a model ecosystem&amp;rdquo;, where I
tracked the evolution of phage genome evolution and the evolution of bacterial
defense mechanisms using metagenomics. When I was writing my thesis I spent a
lot of time writing up the section on
&lt;a href=&#34;http://en.wikipedia.org/wiki/CRISPR&#34;&gt;CRISPRs&lt;/a&gt;, which are a type of bacterial
adaptive immune system. The CRISPR field has exploded in recent times due to its
applications for genome editing which has also meant that there have been
numerous great reviews on the ever expanding primary literature. Despite this
though I found the CRISPR page on wikipedia to be a bit bare (of course now that
I&amp;rsquo;ve updated it things look better, but check out the edit history for a look at
what I&amp;rsquo;ve added). Since there was already a saturation of reviews on the subject
I decided to go through and add in what I had written for my thesis to
wikipedia. By far the most important &lt;strong&gt;and difficult&lt;/strong&gt; part of this is was
formatting the references right. So I made a simple workflow for getting what I
wanted out of my thesis and into wikipedia.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First thing, I wrote my thesis in word and used endnote to format my
references using the style from nucleic acids research (which is a numbered
style). If you want to use my method you need to have the exact formatting
style&lt;/li&gt;
&lt;li&gt;Export the literature review from word as plain text and then removed
all the parts that aren&amp;rsquo;t needed&lt;/li&gt;
&lt;li&gt;Put back in some formatting for the headers using
&lt;a href=&#34;https://en.wikipedia.org/wiki/Help:Cheatsheet&#34;&gt;wikipedia&amp;rsquo;s markup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Split out the bibliography into a separate file&lt;/li&gt;
&lt;li&gt;Then use some very dodgy &lt;a href=&#34;http://github.com/ctSkennerton/wikipedia_reference_formatter&#34;&gt;perl code&lt;/a&gt;
I wrote to format all of the in text citations into the format that wikipedia
requires&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This perl code takes the text and looks for numbers, or lists of numbers inside
parentheses. For example: (1,2,5), (1-7,14), (1). Then looks up what those
references are in the bibliography, extracting the title of the journal article.
Then it looks up what the pubmed ID is for that paper using
&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/books/NBK179288/&#34;&gt;entrezdirect&lt;/a&gt; with the title as
the search term. After getting the pubmed IDs for all the cited references it
saves them to a file, so that it can be used later on (without looking up the
pubmed IDs again) and any errors can be fixed manually. Finally all of those in
text citations are replaced with the proper wikipedia markup and your ready to
upload.&lt;/p&gt;
&lt;p&gt;There are so many scientific wikipedia pages that are way too brief for their
subject matter and I&amp;rsquo;m not just talking about the thousands of stubs for
bacterial and archaeal species either. My current work is with methane seep
sediment communities that perform &lt;a href=&#34;https://en.wikipedia.org/wiki/Anaerobic_oxidation_of_methane&#34;&gt;anaerobic oxidation of
methane&lt;/a&gt; (AOM),
the wikipedia page contains five paragraphs. Looking at the broader topic of
&lt;a href=&#34;https://en.wikipedia.org/wiki/Methanogenesis&#34;&gt;methanogenesis&lt;/a&gt; there is still
only three short paragraphs on the biochemistry. We know so much more than this,
all that knowledge fills the pages of hundreds of review articles yet when
someone, anyone types anything into google the first match that comes up is
wikipedia. We should make it better cause it&amp;rsquo;s ultimately the most visible
publication on the internet.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>My First Useful Script</title>
			<link>/2014/06/23/my-first-useful-script/</link>
			<pubDate>Mon, 23 Jun 2014 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2014/06/23/my-first-useful-script/</guid>
			<description>&lt;p&gt;Can you remember the first useful thing that you ever coded? I sure can, and I&amp;rsquo;m
thankful for it every day.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;I&amp;rsquo;ve recently finished writing a little program called &lt;a href=&#34;https://github.com/ctSkennerton/fxtract&#34;&gt;&lt;code&gt;fxtract&lt;/code&gt;&lt;/a&gt;
(which I&amp;rsquo;ve blogged about &lt;a href=&#34;/posts/2013/10/28/testing-out-seqans-multipattern-search-implementations/&#34;&gt;before&lt;/a&gt;)
that acts like grep but returns whole fasta or fastq records from a file. It&amp;rsquo;s
taken me a very long time to write this thing, primarily cause I&amp;rsquo;m writing it
in C++ but now that it&amp;rsquo;s pretty much done I&amp;rsquo;m feeling nostalgic about why I&amp;rsquo;m
writing it in the first place.&lt;/p&gt;
&lt;p&gt;Back in 2010 I was just starting my PhD with &lt;a href=&#34;http://www.ecogenomic.org/users/gene-tyson&#34;&gt;Gene Tyson&lt;/a&gt;
and learning some bioinformatics on a &amp;ldquo;toy&amp;rdquo; dataset (which became my first
&lt;a href=&#34;http://www.plosone.org/article/info%3Adoi%2F10.1371%2Fjournal.pone.0020095&#34;&gt;paper&lt;/a&gt;)
that was a huge 10 Mbp of viral sequence data! At the time I was learning Perl
using this great &lt;a href=&#34;http://www.woolfit.net/perl/classindex.html&#34;&gt;online tutorial&lt;/a&gt;
but I found that I needed some more &amp;ldquo;real-world&amp;rdquo; examples to really get to grips
with the language. I can&amp;rsquo;t fully remember what I was doing but I had a tabular
blast output file and I wanted to get the sequence of some contigs with blast
hits. I jumped at the opportunity to solve this with my nasent coding skills and
so I started writing my first useful bit of code:
&lt;a href=&#34;https://github.com/ctSkennerton/scriptShed/blob/master/contig_extractor.pl&#34;&gt;&lt;code&gt;contig_extractor.pl&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the beginning it did only what I first wrote it to do: take a blast file and
a fasta file and return some contigs. Over time though it morphed into something
more general - a way of getting some subset of a fasta file using a list of
identifiers. Over the years I added functionality for different file formats and
allowed searching using regular expressions.
This one piece of code eventually disseminated throughout the whole lab group
as new people came in and needed to solve the same problems. I think that the
introduction to github for many of the PhD students who came after me
was downloading my random collection of scripts just so they
could get their hands on &lt;code&gt;contig_extractor.pl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course every bioinformatician has probably written the same piece of code
to solve the same problem. If I had been smart enough to look I&amp;rsquo;m sure
that I would have found one, but using a script doesn&amp;rsquo;t quite give the same
level of satisfaction as writing it yourself (and finding that it&amp;rsquo;s useful by all your
colleages).&lt;/p&gt;
&lt;p&gt;There came a time though when &lt;code&gt;contig_extractor.pl&lt;/code&gt; reached it&amp;rsquo;s limit. I was
trying to extract a few thousand records from a fastq file with 100 million and
Perl just wasn&amp;rsquo;t cutting it anymore. And so &lt;code&gt;fxtract&lt;/code&gt; was born to do all the good
things from &lt;code&gt;contig_extractor.pl&lt;/code&gt; just a heap faster.The sun is setting on my
first useful piece of code, at the moment only my finger memory and force of habit
keeps it being used. But when I think about it, it&amp;rsquo;s been an amazing four year run for something that I
probably thought was going to be a one-off script, hopefully &lt;code&gt;fxtract&lt;/code&gt; can get
as much love from me as well.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Finding 16s/18s reads in metagenomes</title>
			<link>/2014/04/19/finding-16s/18s-reads-in-metagenomes/</link>
			<pubDate>Sat, 19 Apr 2014 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2014/04/19/finding-16s/18s-reads-in-metagenomes/</guid>
			<description>&lt;p&gt;Got a Metagenome? want to know what the community looks like?&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;rRNA operons are typically poorly assembled in metagenomic datasets due to
highly conserved sequences.  More targeted assembly approaches may be necessary
to obtain accurate reconstructions from short read datasets. There are a few
ways in which we can extract reads originating from either 16S or 18S reads and
there are a number of programs (&lt;a href=&#34;http://selab.janelia.org/software/ssu-align/&#34;&gt;SSU-ALIGN&lt;/a&gt;,
&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/21887657&#34;&gt;rRNASelector&lt;/a&gt;,
&lt;a href=&#34;http://ribopicker.sourceforge.net/&#34;&gt;riboPicker&lt;/a&gt;,
&lt;a href=&#34;http://bioinfo.lifl.fr/RNA/sortmerna/&#34;&gt;SortMeRNA&lt;/a&gt;,
blast, &lt;a href=&#34;http://bowtie-bio.sourceforge.net/bowtie2/index.shtml&#34;&gt;bowtie&lt;/a&gt; or &lt;a href=&#34;https://github.com/lh3/bwa&#34;&gt;bwa&lt;/a&gt;) to name a few.&lt;/p&gt;
&lt;p&gt;There are a other ways of looking at the communty from raw metagenomic
reads. These are mostly kmer-based approaches like
&lt;a href=&#34;http://ccb.jhu.edu/software/kraken/&#34;&gt;kraken&lt;/a&gt; or extended marker gene
approaches like
&lt;a href=&#34;http://huttenhower.sph.harvard.edu/metaphlan&#34;&gt;MetaPhlAn&lt;/a&gt; or
&lt;a href=&#34;http://phylosift.wordpress.com/&#34;&gt;phylosift&lt;/a&gt;. I&amp;rsquo;m not against any of
them, just never used them, so I&amp;rsquo;m going to keep the following post
specific to 16s/18s community composition&lt;/p&gt;
&lt;h2 id=&#34;extracting-16s18s-reads&#34;&gt;Extracting 16S/18S reads&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve used SortMeRNA and bowtie/bwa in my workflows with good success. The
difference between these two methods is that SortMeRNA that uses a kmer
searching method using an index created from a database of previously sequenced
genes whereas bowtie/bwa use a local alignment method to compare the query sequence to
a previously made database. Below are instructions on how to use both methods.&lt;/p&gt;
&lt;h2 id=&#34;installing-and-using-sortmerna&#34;&gt;Installing and using SortMeRNA&lt;/h2&gt;
&lt;p&gt;From the source page for SortMeRNA on &lt;a href=&#34;https://github.com/biocore/sortmerna&#34;&gt;github&lt;/a&gt;
copy the ssh clone url and then open up a terminal window and type&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ git clone git@github.com:biocore/sortmerna.git
$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; sortmerna
$ ./configure --prefix&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PWD&lt;/span&gt;
$ make install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Mac OSX install note:&lt;/strong&gt; I found that there was an error with my install
with &lt;code&gt;configure&lt;/code&gt; complaining that it was missing &lt;code&gt;install-sh&lt;/code&gt;. I solved this by
copying &lt;a href=&#34;http://sourceforge.net/projects/buildconf/&#34;&gt;autogen.sh&lt;/a&gt; into the same
directory as &lt;code&gt;configure&lt;/code&gt;, execute it and then try running configure again.&lt;/p&gt;
&lt;p&gt;The commands above should install SortMeRNA in the directory which you downloaded
it to.&lt;/p&gt;
&lt;h4 id=&#34;building-indexes-for-sortmerna&#34;&gt;Building indexes for SortMeRNA&lt;/h4&gt;
&lt;p&gt;SortMeRNA comes packaged with 8 different rRNA databases, all derived from SILVA.
Build either the 16S or 18S database, depending on what you want. Below is the
command used to generate the 18S index (assuming that you&amp;rsquo;ve installed in the
download directory)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ bin/indexdb_rna --ref rRNA_databases/silva-euk-18s-database-id95.fasta,index/silva-euk-18s-database-id95 --sensitive
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you &lt;code&gt;ls&lt;/code&gt; the index directory you should see four files generated.&lt;/p&gt;
&lt;h4 id=&#34;preprocessing-reads&#34;&gt;Preprocessing reads&lt;/h4&gt;
&lt;p&gt;Now we can use this index to extract the reads that may come from 18S using the
&lt;code&gt;sortmerna&lt;/code&gt; command. I&amp;rsquo;m going to assume that there are files containing raw
reads from an Illumina run called &lt;code&gt;file_R1.fastq.gz&lt;/code&gt; and &lt;code&gt;file_R2.fastq.gz&lt;/code&gt;.
Unfortunately one of the limitations of SortMeRNA is that it requires that you
only give it a single file and that the file is uncompressed. So to start with,
unzip the files using &lt;code&gt;gzip&lt;/code&gt; and then combine them into a single file using
&lt;code&gt;merge-paired-reads.sh&lt;/code&gt; found in the scripts directory of the SortMeRNA source
code&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ gunzip file_R1.fastq.gz file_R2.fastq.gz
$ bash scripts/merge-paired-reads.sh file_R1.fastq file_R2.fastq combined.fastq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To save space, it&amp;rsquo;s probably best to re-zip the files to save on harddrive space&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ gzip file_R1.fastq file_R2.fastq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;extracting-the-reads&#34;&gt;Extracting the reads&lt;/h4&gt;
&lt;p&gt;Now we can run &lt;code&gt;sortmerna&lt;/code&gt;, saving matched reads (and their mates) to a file
with the prefix &amp;lsquo;matched-18S&amp;rsquo; in fastq format using 4 processors.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ bin/sortmerna --reads combined.fastq &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --ref rRNA_databases/silva-euk-18s-database-id95.fasta,index/silva-euk-18s-database-id95 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --paired-in &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --fastx &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --aligned matched-18S &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    -a &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;installing-and-using-bwa&#34;&gt;Installing and using BWA&lt;/h2&gt;
&lt;p&gt;My personal preference is to use bwa over bowtie but the merits of either are
debatable (there are also 50 other programs out there that try to solve the same
problem so the choice is yours). Download bwa from &lt;a href=&#34;https://github.com/lh3/bwa&#34;&gt;github&lt;/a&gt;
by copying the ssh clone url and typing the following into the terminal. (Change
directories out of the SortMeRNA source directory before you do this)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ git clone git@github.com:lh3/bwa.git
$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; bwa
$ make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;bwa also requires that an index of the database be made. For simplicity, lets
use the same database that was included in SortMeRNA. To make the bwa index
copy the files that you want from the SortMeRNA source directory into a new
location.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ cp ../sortmerna/rRNA_databases/silva-euk-18s-database-id95.fasta .
$ bwa index silva-euk-18s-database-id95.fasta
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should make a whole bunch of files that have extra file extensions appended
to the fasta file. With the index created we can now align the reads&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ bwa mem silva-euk-18s-database-id95.fasta file_R1.fastq.gz file_R2.fastq.gz &amp;gt; aligned_18S.sam
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(Notice that there is no preprocessing steps necessary for the reads)&lt;/p&gt;
&lt;h4 id=&#34;postprocessing-the-sam-file&#34;&gt;Postprocessing the sam file&lt;/h4&gt;
&lt;p&gt;The output of bwa is a standardized format called &lt;a href=&#34;http://samtools.github.io/hts-specs/SAMv1.pdf&#34;&gt;sam&lt;/a&gt;
which many programs will now output. This format essentially describes the
alignment of each of the query sequences to the reference sequences. This is
not exactly what we want, which is the reads that were successful hits to the
reference in fasta/q format. To go from a sam file to a fasta/q file is a little
complicated (I wish it wasn&amp;rsquo;t). To start with, download &lt;a href=&#34;https://github.com/samtools/samtools&#34;&gt;samtools&lt;/a&gt;
and &lt;a href=&#34;https://github.com/ctSkennerton/fxtract&#34;&gt;fxtract&lt;/a&gt; from github, and download
them into new source directories (bonus points for getting them installed without
a walkthrough). First convert the sam file into its equivalent binary format and
filter out unaligned sequences:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ samtools view -SubF &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; aligned_18S.sam &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; samtools sort - aligned_18S &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; samtools index aligned_18S.bam
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now get the names of all the reads that aligned:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ samtools view aligned_18S.bam &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; cut -f &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &amp;gt;aligned_reads.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally extract those reads from the original fastq files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;$ fxtract -Hf aligned_reads.txt file_R1.fastq.gz file_R2.fastq.gz &amp;gt;aligned_reads.fastq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
		<item>
			<title>Poking around inside grep</title>
			<link>/2013/12/27/poking-around-inside-grep/</link>
			<pubDate>Fri, 27 Dec 2013 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2013/12/27/poking-around-inside-grep/</guid>
			<description>&lt;p&gt;Playing around with the grep source code to make it output fasta/fastq records.
Check out the code &lt;a href=&#34;https://github.com/ctSkennerton/fagrep&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;I&amp;rsquo;m quite interested in string searching algorithms as I&amp;rsquo;ve written a
program, &lt;a href=&#34;http://ctskennerton.github.io/crass&#34;&gt;crass&lt;/a&gt;, which uses a few of them
to search for CRISPR elements.  Crass is pretty fast, but I want it to be faster,
specifically there is one point in crass where it searches for exact matches to many
thousands of patterns.
In a &lt;a href=&#34;/2013/10/28/testing-out-seqans-multipattern-search-implementations/&#34;&gt;previous post&lt;/a&gt;
I tried out a number of different &amp;lsquo;multi-pattern matchers&amp;rsquo; from &lt;a href=&#34;http://seqan.de&#34;&gt;seqan&lt;/a&gt;
and was fairly unimpressed with their speed.  In this testing though I did not try
out the most widely used implementations of multi-pattern matching: GNU grep (using &lt;code&gt;-Ff&lt;/code&gt; options).  I don&amp;rsquo;t have any graphs to show, but it was faster, like &lt;strong&gt;a lot&lt;/strong&gt; faster.&lt;/p&gt;
&lt;p&gt;It wasn&amp;rsquo;t a fair fight though, as grep works very differently to my test program
fxtract.  There is a great mailing list &lt;a href=&#34;http://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html&#34;&gt;post&lt;/a&gt;
by one of the original grep authors on ways to speed things up.  It basically
comes down to I/O (not that the search algorithms aren&amp;rsquo;t highly optimised themselves),
fast input from a file and not copying the data in memory is the key.  Grep doesn&amp;rsquo;t
try to parse the file instead it just loads it into a big buffer in memory and searches
the whole thing, if it finds a match then it figures out the boundaries of the line
the match is on and prints it out.  This is in contrast to programs like fxtract or
crass that parse the file first to get the individual portions of each record before
the search is performed.&lt;/p&gt;
&lt;p&gt;This got me thinking that I could drastically speed crass up if I switched over
to the grep way of processing files.  I was a little worried though that determining
the boundaries of a fasta/fastq record from an anonymous buffer might be a bit tricky
so before I modified crass I chose to modify grep so that it would output
fasta or fastq records.&lt;/p&gt;
&lt;p&gt;The printing functions in grep live in &lt;code&gt;main.c&lt;/code&gt; and start with the function &lt;code&gt;grep&lt;/code&gt;, which
in-turn calls &lt;code&gt;grepbuf&lt;/code&gt;, which in-turn calls &lt;code&gt;prtext&lt;/code&gt; etc.  The code is surprisingly simple,
&lt;code&gt;grep&lt;/code&gt; reads from the file and fills a buffer; &lt;code&gt;grepbuf&lt;/code&gt; executes
one of the search functions on that buffer; if a match is found, a pointer to the first
character in the line the match was found is returned; and then the printing functions
take over.  The printing functions get a pointer to the start of the line and the end
of the line of the match and pass that through to &lt;code&gt;fwrite&lt;/code&gt;.  Everything is handled using
pointer arithmetic for determining the start and end of where to print.&lt;/p&gt;
&lt;p&gt;This is great since it&amp;rsquo;s easy to change the pointer to the beginning a end of a record, rather
than a line.  So that just left the logic for me to write in to find the limits of
a record.  Below is a code snippet from grep where I&amp;rsquo;ve added in the logic.  Fasta is
easy to implement as the &lt;code&gt;&amp;gt;&lt;/code&gt; symbol is generally unique.  Fastq on the other hand takes
a bit more work, since the &lt;code&gt;@&lt;/code&gt; symbol can also be found in the quality string.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match_offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;cm&#34;&gt;/*pointer to beginning of matching line*/&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/*pointer to end of matching line*/&lt;/span&gt;
&lt;span class=&#34;cm&#34;&gt;/* Avoid matching the empty line at the end of the buffer. */&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fasta_input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;cm&#34;&gt;/*find the beginning of the record*/&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;cm&#34;&gt;/*find the end of the record*/&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lim&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fastq_input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;cm&#34;&gt;/*find the beginning of the record*/&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; 
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;@&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
          &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;beg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
              &lt;span class=&#34;cm&#34;&gt;/*can&amp;#39;t go back any further therefore must be start of record*/&lt;/span&gt;
              &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;+&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
              &lt;span class=&#34;cm&#34;&gt;/*@ symbol at beginning of line but not the first in the quality */&lt;/span&gt;
              &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
          &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
      &lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;newline_count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;newline_count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;newline_count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;newline_count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;cm&#34;&gt;/*find the end of the record*/&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lim&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
          &lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    
        &lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The fastq format parsing has fairly obvious corner cases since with this
code there can be no text on the &amp;lsquo;comment&amp;rsquo; line and the whole
record must be of four lines.  This version of fastq is the recommended formatting from the
official &lt;a href=&#34;http://nar.oxfordjournals.org/content/38/6/1767.full&#34;&gt;fastq publication&lt;/a&gt;,
which seems to have been adopted by Illumina and others, so hopefully this simple
parsing will work most of the time.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s been a heap of fun looking at the way this very mature piece of software works
and I&amp;rsquo;ve gotten a usable tool out of it.  Now it&amp;rsquo;s onto the main event of
ripping out parts of the source code that I want for crass&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Genome Scaffolders Suck</title>
			<link>/2013/12/11/genome-scaffolders-suck/</link>
			<pubDate>Wed, 11 Dec 2013 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2013/12/11/genome-scaffolders-suck/</guid>
			<description>&lt;p&gt;Experiences using a variety of contig scaffolding tools. It was not a good experience.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Recently in our lab we&amp;rsquo;ve been getting some Illumina mate-pair data to
improve some metagenomic assemblies.  The sequencing has been going
well and we&amp;rsquo;ve been generating a good number of mate-pairs without too much
duplication, but we&amp;rsquo;ve had quite a bit of trouble with the bioinformatic part
of actually using this data to improve the assemblies.  There are a number of
software tools available to link contigs together after an assembly has been
done, however many assume that you are scaffolding a genome not a &lt;em&gt;meta&lt;/em&gt;genome.&lt;br&gt;
One of my colleagues suggested that, as a group, we perform a comparison of these
programs to determine which is the best one to suit our needs.&lt;/p&gt;
&lt;p&gt;We decided to test out &lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/21149342&#34;&gt;sspace&lt;/a&gt;,
&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/22492642&#34;&gt;grass&lt;/a&gt;,
&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/23274213&#34;&gt;scarpa&lt;/a&gt;,
&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/21929371&#34;&gt;opera&lt;/a&gt;,
&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/21998153&#34;&gt;mip&lt;/a&gt; and
&lt;a href=&#34;http://www.ncbi.nlm.nih.gov/pubmed/21926123&#34;&gt;bambus2&lt;/a&gt;.
From these six programs, only bambus2 was designed for metagenomes.
To test how well genome scaffolders could transition into
metagenome scaffolders we took one of our metagenomes and randomly broke
up 1000 contigs formed only using paired-end data into two pieces and
attempted to use some shiny new mate-pair data to put the pieces back
together again.  Little did we know the world of pain that we were about
to step into&amp;hellip;&lt;/p&gt;
&lt;p&gt;The following post will not talk about which algorithm was better or even
really what results each of these programs gave.  No, I&amp;rsquo;m going to talk
about why using all these programs sucked.&lt;/p&gt;
&lt;h2 id=&#34;the-war-of-attrition&#34;&gt;The war of attrition&lt;/h2&gt;
&lt;h3 id=&#34;grass&#34;&gt;grass&lt;/h3&gt;
&lt;p&gt;We didn&amp;rsquo;t even get &lt;em&gt;grass&lt;/em&gt; installed; it required a particular library
distributed by IBM, which while free for academic users, required you to
give over some personal details, which we decided was something that we
didn&amp;rsquo;t want to do.&lt;/p&gt;
&lt;p&gt;One down, five to go&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;mip&#34;&gt;mip&lt;/h3&gt;
&lt;p&gt;Oh where do I start with &lt;em&gt;mip&lt;/em&gt;! &lt;em&gt;Mip&lt;/em&gt; assumes that you&amp;rsquo;re using SOLiD
data, which means that it expects that the orientation of the reads are
forward-forward.  Since Illumina&amp;rsquo;s mate-pairs are reverse-forward I
needed to reverse complement the first read, making a duplicate file.  But
actually I needed to modify the second read file as well because &lt;em&gt;mip&lt;/em&gt;
needs to have the read identifiers ending in &amp;ldquo;_R3&amp;rdquo; or &amp;ldquo;_F3&amp;rdquo; (WTF!), just
like they would be for a SOLiD run.  After this, I could then run any short-read
mapper to produce a SAM file for further processing.  But wait, you have
to map each read separately (i.e. not as pairs) and then pass the SAM
file through two preprocessing shell scripts.  The first of these shell
scripts, the opaquely named &lt;code&gt;merge.sh&lt;/code&gt; simply takes the corresponding
SAM alignment record from the first and second reads and concatenates
the lines!  Why this needed to be a separate script and not just part of
the software proper is beyond me. Both of these preprocessing scripts created new files that
were essentially duplicates of the original SAM files made by the
short-read mapper, which I truly find annoying, especially since our
server is currently short on storage space.&lt;/p&gt;
&lt;p&gt;When I ran &lt;em&gt;mip&lt;/em&gt; proper, it threw an error.  That error may have been
easy for me to fix, it might have been something silly that I had put
into &lt;em&gt;mip&amp;rsquo;s&lt;/em&gt; configuration file, I don&amp;rsquo;t know.  At this point I was pissed
about the whole process and never tried to run the program again.&lt;/p&gt;
&lt;p&gt;Two down, four to go&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;opera&#34;&gt;opera&lt;/h3&gt;
&lt;p&gt;It segfaulted on the test data that came with the software.&lt;/p&gt;
&lt;p&gt;Three down, three to go&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;bambus2&#34;&gt;bambus2&lt;/h3&gt;
&lt;p&gt;I had hope for bambus, and this was the scaffolder which I put the most
amount of effort to get it to work.  The problem with bambus is
that it is part of the &lt;a href=&#34;http://sourceforge.net/apps/mediawiki/amos/index.php?title=AMOS&#34;&gt;AMOS&lt;/a&gt;
software package and the problem with AMOS is that it is fairly old
and uses it&amp;rsquo;s own file format.  I have no doubt that the authors of AMOS
were hoping that their file format would catch on and that many tools
would plug into it, but alas the AMOS file format did not catch on,
instead we have SAM files.  So I set about looking for a SAM to AMOS
file converter, and I found &lt;a href=&#34;http://sourceforge.net/p/amos/code/ci/master/tree/src/Converters/samtoafg.pl&#34;&gt;one&lt;/a&gt;
in the AMOS package.  It was a nice little perl script that
unfortunately didn&amp;rsquo;t work (once again threw an error).&lt;/p&gt;
&lt;p&gt;I decided to write my own converter in C++ using the
&lt;a href=&#34;https://github.com/pezmaster31/bamtools&#34;&gt;bamtools&lt;/a&gt; and AMOS C++ APIs.
The fruits of my labour was the program &lt;a href=&#34;https://github.com/ctSkennerton/sam2amos&#34;&gt;sam2amos&lt;/a&gt;,
which can take a BAM file and convert it into either an AMOS message
stream or an AMOS bank.  I was honestly really impressed with the
simplicity of both of these APIs, which made writing this program
relatively easy.&lt;/p&gt;
&lt;p&gt;After making my AMOS bank file with sam2amos I ran the &lt;code&gt;goBambus2.py&lt;/code&gt; wrapping script,
which unfortunately resulted in bambus segfaulting. Bugger!  I didn&amp;rsquo;t
have it in me to debug the situation and figure out whether it was caused by a problem in
sam2amos (which it probably is) or something else.&lt;/p&gt;
&lt;p&gt;Four down, two to go&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;finally-some-results&#34;&gt;Finally some results&lt;/h2&gt;
&lt;h3 id=&#34;scarpa&#34;&gt;scarpa&lt;/h3&gt;
&lt;p&gt;I never personally ran &lt;em&gt;scarpa&lt;/em&gt; (one of my colleagues did) but it shared some of the
annoyances that &lt;em&gt;mip&lt;/em&gt; had.  &lt;em&gt;Scarpa&lt;/em&gt; assumes that the reads are in
forward-reverse orientation so it required that both of the reads be
reverse complemented before use.  Like &lt;em&gt;mip&lt;/em&gt;, the reads needed to be
mapped independently.  But unlike &lt;em&gt;mip&lt;/em&gt;, &lt;em&gt;scarpa&lt;/em&gt; gave some results!!
Of course the output was a simple fasta file of scaffolds without any
indication of what contigs were actually put together.  A little more
information would have been nice&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;sspace&#34;&gt;sspace&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Sspace&lt;/em&gt; is the best of the bunch when it comes to usability.  You can
specify what orientation the reads were in and there was only one manual
preprocessing step required; &lt;em&gt;sspace&lt;/em&gt; does not accept compressed files so
the reads had to be passed through &lt;code&gt;ungzip&lt;/code&gt; before use.  &lt;em&gt;Sspace&lt;/em&gt; does however have some annoying
automatic preprocessing steps. First, the reads are copied into the
output directory (why? I don&amp;rsquo;t know). Second, &lt;em&gt;sspace&lt;/em&gt; only runs bowtie,
you cannot specify any other mapper, this isn&amp;rsquo;t so much of a problem but
it annoyingly repeats the mapping even if the results from a previous
run exist in the output directory.  The output though is better than
&lt;em&gt;scarpa&amp;rsquo;s&lt;/em&gt; as it gives you a fasta file of scaffolds, an &amp;ldquo;evidence file&amp;rdquo; actually
telling you how it put contigs together and optionally a graphviz file
so that you can look at the contig linkages.&lt;/p&gt;
&lt;h2 id=&#34;what-i-want-from-a-scaffolder&#34;&gt;What I want from a scaffolder&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;The ability to take either a SAM or BAM file of read mappings; or&lt;/li&gt;
&lt;li&gt;If a particular read mapper is really required, give me the ability
to set the read orientation and used commpressed input files&lt;/li&gt;
&lt;li&gt;One that uses pipes and does not copy reads into an output
directory. The less file I/O the better&lt;/li&gt;
&lt;li&gt;No configureation files, I want to pipeline this thing, give me some
command-line options&lt;/li&gt;
&lt;li&gt;Tell me how the scaffolding was done with some sort of easy tabular
file format.  Better yet make that output format &lt;a href=&#34;http://www.ncbi.nlm.nih.gov/projects/genome/assembly/agp/AGP_Specification.shtml&#34;&gt;AGP&lt;/a&gt;,
which is required by NCBI when uploading scaffolds.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;epilogue&#34;&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;Oh yeah, &lt;em&gt;sspace&lt;/em&gt; gave better results than &lt;em&gt;scarpa&lt;/em&gt;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Testing out Seqan&#39;s Multipattern Search Implementations</title>
			<link>/2013/10/28/testing-out-seqans-multipattern-search-implementations/</link>
			<pubDate>Mon, 28 Oct 2013 00:00:00 +0000</pubDate>
			<author>c.skennerton@gmail.com (Connor Skennerton)</author>
			<guid isPermaLink="true">/2013/10/28/testing-out-seqans-multipattern-search-implementations/</guid>
			<description>&lt;p&gt;I recently discovered &lt;a href=&#34;http://seqan.de&#34;&gt;Seqan&lt;/a&gt;, a header-only C++ library for
bioinformatics.  I&amp;rsquo;ve been playing around with the toolkit to make some
small programs just to see whether I want to use it in a
larger project.  So far I&amp;rsquo;ve written
&lt;a href=&#34;https://github.com/ctSkennerton/prepmate&#34;&gt;prepmate&lt;/a&gt;, an adaptor trimming
program for Illumina&amp;rsquo;s Nextera mate-pair libraries; and
&lt;a href=&#34;https://github.com/ctSkennerton/fxtract&#34;&gt;fxtract&lt;/a&gt;, a
grep-like program for extracting fasta/fastq records from large files.  One of the
algorithms that I use in fxtract and in another program I&amp;rsquo;ve written,
&lt;a href=&#34;http://ctskennerton.github.io/crass/&#34;&gt;crass&lt;/a&gt;, is to search for
multiple patterns simultaneously (in this case a number of different DNA
motifs).  Seqan
implements a number of algorithms for multipattern matching (checkout
their tutorial page), however they don&amp;rsquo;t give many clues as to why you
would choose one algorithm over another.  So I decided to take a few of
these implementations out for a spin using fxtract.&lt;/p&gt;
&lt;h4 id=&#34;test-variables&#34;&gt;Test variables:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;different numbers of patterns: 100, 1000, 10000&lt;/li&gt;
&lt;li&gt;different length patterns: uniformly distributed size (0 - 100bp), 30bp,
60bp&lt;/li&gt;
&lt;li&gt;Algorithms: WuManber, MultiBfam, AhoChorasick, SetHorspool&lt;/li&gt;
&lt;li&gt;Test dataset: &lt;a href=&#34;http://trace.ncbi.nlm.nih.gov/Traces/sra/sra.cgi?cmd=viewer&amp;amp;m=data&amp;amp;s=viewer&amp;amp;run=SRR438796&#34;&gt;SRR438796&lt;/a&gt;,
which is part of an EBPR metagenome that was sequenced with Illumina GAIIx&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I should point out the the following speed tests are not necessarily
testing the algorithms, but the seqan implementation of these
algorithms in the context of what fxtract is trying to accomplish.  Which
means that other programs which implement these algorithms may perform
quite differently and the conclusions that I reach below may be
different in other situations. So with disclamers out of the way, how
does each implementation perform.&lt;/p&gt;
&lt;p&gt;While running through a test of the wumanber implementation I discovered
something very odd when using the uniformly distributed patterns.  With
100 patterns the program ran through fine, outputting the correct
results,
however when using the 1000 or 10000 pattern file I got no output.  I
discovered though that these larger files contained some patterns that
had a length of 0 (i.e. they were empty lines), whereas the 100 pattern file&amp;rsquo;s smallest pattern was
6bp.  I removed the empty lines from my pattern files and then and voila
there was output.  What this means is that &lt;strong&gt;the seqan WuManber
implementation fails silently when given an empty string as one of the
patterns!&lt;/strong&gt; I&amp;rsquo;ve submitted a &lt;a href=&#34;http://trac.seqan.de/ticket/1117&#34;&gt;bug report&lt;/a&gt;
with the seqan authors.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;/media/seqan_multipattern_search_speed_benchmark.png&#34;
         alt=&#34;Seqan speed test summary&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Seqan speed test summary&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The above graph shows the total wall clock time in seconds for each
algorithm to process the input file with the different numbers of search
patterns (columns) or for the different types of patters (rows).&lt;br&gt;
The main thing that striked me was the poor performance of the&lt;br&gt;
seqan implementation of the Wu-Manber algorithm - it does not scale well.&lt;/p&gt;
&lt;p&gt;I was lead to believe that Wu-Manber was the pinicle of multipattern
searching so I was a little perplexed by this result.  I know of another
stand alone implementation of Wu-Manber provided by &lt;a href=&#34;http://www.oneunified.net/blog/2008/03/23/&#34;&gt;Ray
Burkholder&lt;/a&gt;.  As a
comparison I tested out this implementation as well and perhaps
unsurprisingly this implementation performed much better (it&amp;rsquo;s referred
to in the figures as &amp;ldquo;non-seqan wu-manber&amp;rdquo;). &lt;strong&gt;Bottom line:
So don&amp;rsquo;t use the Wu-Manber implementation in Seqan!&lt;/strong&gt;  The
winner of the speed benchmark was the multiBfam algorithim which
performed nearly identically for any number of input patterns or for the
different length patterns.  In comparison the Aho-Corasick and
SetHorspool algorithms became slower with more patterns.&lt;/p&gt;
&lt;p&gt;Speed tells you only half of the story and usually comes at the price of
memory consumption.  Both of the Wu-Manber implementations excelled at
memory consumption, or lack there of.  The worst were the Aho-Corasick
and SetHorspool algorithms, which used 20Gb+ of memory under the worst
case.  The multiBfam algorithm was somewhere in the middle (~7Gb under
the worst case scenario).&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;/media/seqan_multipattern_search_memory_benchmark.png&#34;
         alt=&#34;Seqan speed test summary&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;Seqan speed test summary&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Considering only the seqan implementations I would probably go for the
multiBfam algorithm as my first choice when searching for less than 1000
patterns after which Wu-Manber would have to be preferred.&lt;br&gt;
Base on what I&amp;rsquo;ve seen the Aho-Corasick and SetHorspool implementations
in seqan are the worst options as they use far too much memory, however
that&amp;rsquo;s not to say that other implementations of these algorithms would
perform differently.&lt;/p&gt;
&lt;h2 id=&#34;scripts&#34;&gt;Scripts&lt;/h2&gt;
&lt;h4 id=&#34;make_patternssh&#34;&gt;make_patterns.sh&lt;/h4&gt;
&lt;p&gt;Running this script requires that both &lt;a href=&#34;https://github.com/lh3/seqtk&#34;&gt;seqtk&lt;/a&gt;
and &lt;a href=&#34;https://github.com/lh3/bioawk&#34;&gt;bioawk&lt;/a&gt; are installed
and in your PATH.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; count in &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10000&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# make uniformly distributed patterns&lt;/span&gt;
    seqtk sample SRR438796.fastq.gz
&lt;span class=&#34;nv&#34;&gt;$count&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;        bioawk -c fastx &lt;span class=&#34;s1&#34;&gt;&amp;#39;{
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            start=rand() *99;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            end=rand() * 99;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            if(start &amp;lt; end){                 
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;                if(end - start &amp;gt; 15) {
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;                    print substr($seq, start, end)             
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;                }
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            }else{
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;                if(start - end &amp;gt; 15) {
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;                    print substr($seq, end, start)
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;                }
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;             }         
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;}&amp;#39;&lt;/span&gt; &amp;gt;random_&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_patterns.txt

    &lt;span class=&#34;c1&#34;&gt;# make 30bp patterns&lt;/span&gt; 
    seqtk sample SRR438796.fastq.gz
&lt;span class=&#34;nv&#34;&gt;$count&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;        bioawk -c fastx &lt;span class=&#34;s1&#34;&gt;&amp;#39;{
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            start=rand() * 30;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            end=start + 30;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            print substr($seq, start, end)
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;        }&amp;#39;&lt;/span&gt; &amp;gt;random_&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_30bp_patterns.txt

    &lt;span class=&#34;c1&#34;&gt;# make 60bp patterns&lt;/span&gt;
    seqtk sample SRR438796.fastq.gz
&lt;span class=&#34;nv&#34;&gt;$count&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;        bioawk -c fastx &lt;span class=&#34;s1&#34;&gt;&amp;#39;{
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            start=rand() * 30;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            end=start + 60;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;            print substr($seq, start, end)
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;        }&amp;#39;&lt;/span&gt; &amp;gt;random_&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_60bp_patterns.txt
&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;####time_implementations.sh&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#! /bin/bash
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; impl in fxtract-*
&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; p in speed_test/random_100*
    &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
        &lt;span class=&#34;nv&#34;&gt;patterns&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;basename &lt;span class=&#34;nv&#34;&gt;$p&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;real,user,sys,avemem,maxmem&amp;#34;&lt;/span&gt; &amp;gt;speed_test/&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;patterns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;%.txt&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_times.txt
        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; i in &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;1..10&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
            /usr/bin/time -f &lt;span class=&#34;s2&#34;&gt;&amp;#34;%E,%U,%S,%K,%M&amp;#34;&lt;/span&gt; -a -o speed_test/&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;patterns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;%.txt&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_times.txt ./&lt;span class=&#34;nv&#34;&gt;$impl&lt;/span&gt; -f &lt;span class=&#34;nv&#34;&gt;$p&lt;/span&gt; SRR438796.fastq.gz &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\ &lt;/span&gt;
                wc -l &amp;gt;&amp;gt;speed_test/&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;patterns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;%.txt&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;_words.txt
        &lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;summarize_timespy&#34;&gt;summarize_times.py&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;__future__&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;print_function&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;glob&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;re&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;fixed_re&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;re&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;compile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;fxtract-(\w+)_random_(10{2,5})_(\d\d)bp_patterns_times\.txt&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;norm_re&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;re&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;compile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;fxtract-(\w+)_random_(10{2,5})_patterns_minus_small_times\.txt&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;impl_codes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ac&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;aho-corasick&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;sh&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;set horspool&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;mb&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;multi-bfam&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;wm&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;wu-manber&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;times_files&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;glob&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;glob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;./fxtract*times.txt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;times_files&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fixed_re&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;search&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;impl&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;impl_codes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;pattern_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;pattern_count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;norm_re&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;search&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;impl&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;impl_codes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;pattern_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;norm&amp;#39;&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;pattern_count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Filename &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%s&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; does not fit either form&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;first_line&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;True&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;first_line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;first_line&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;False&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rstrip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fields&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;10.0&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pattern_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pattern_count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\t&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;plot_summaryr&#34;&gt;plot_summary.R&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read.table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;summary.txt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;\t&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algorithm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Wall.time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;geom_bar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stat&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;png&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;seqan_multipattern_search_speed_benchmark.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;facet_grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Pattern.type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Number.of.patterns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axis.text.x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;angle&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;45&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;dev.off&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
		</item>
	</channel>
</rss>
