<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Adrin's Blog</title><link href="https://adrin.info/" rel="alternate"/><link href="https://adrin.info/feeds/all.atom.xml" rel="self"/><id>https://adrin.info/</id><updated>2025-09-10T00:00:00+02:00</updated><entry><title>The Cost of AI in Open Source Maintenance</title><link href="https://adrin.info/the-cost-of-ai-in-open-source-maintenance.html" rel="alternate"/><published>2025-09-10T00:00:00+02:00</published><updated>2025-09-10T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2025-09-10:/the-cost-of-ai-in-open-source-maintenance.html</id><summary type="html">&lt;p&gt;&lt;img alt="The burden of AI" src="files/img/20250910-AI-maintenance.png"&gt;&lt;/p&gt;
&lt;h1 id="being-a-maintainer-in-the-age-of-ai"&gt;Being a maintainer in the age of &lt;span class="caps"&gt;AI&lt;/span&gt;.&lt;a class="headerlink" href="#being-a-maintainer-in-the-age-of-ai" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Ralf Gommers wrote a really nice blog post around 6 years ago about &lt;a href="https://rgommers.github.io/2019/06/the-cost-of-an-open-source-contribution/"&gt;the cost of
an open source contribution
&lt;/a&gt;,
where he talks about what happens when a contribution comes in, the challenges,
and the bottlenecks. Since then, open source has become …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="The burden of AI" src="files/img/20250910-AI-maintenance.png"&gt;&lt;/p&gt;
&lt;h1 id="being-a-maintainer-in-the-age-of-ai"&gt;Being a maintainer in the age of &lt;span class="caps"&gt;AI&lt;/span&gt;.&lt;a class="headerlink" href="#being-a-maintainer-in-the-age-of-ai" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Ralf Gommers wrote a really nice blog post around 6 years ago about &lt;a href="https://rgommers.github.io/2019/06/the-cost-of-an-open-source-contribution/"&gt;the cost of
an open source contribution
&lt;/a&gt;,
where he talks about what happens when a contribution comes in, the challenges,
and the bottlenecks. Since then, open source has become even more mainstream,
and the number of contributors has gone up, while the number of maintainers in
many projects staying more or less the&amp;nbsp;same.&lt;/p&gt;
&lt;p&gt;On top of that, with the expansion of &lt;span class="caps"&gt;AI&lt;/span&gt; tools and their general availability,
an increasing number of people seem to be trying their luck at &amp;#8220;vibe
contributing&amp;#8221; to open source, which is an issue when the contributions are
submitted w/o a proper human review and when the contributor doesn&amp;#8217;t understand
their own submission; and it&amp;#8217;s quite easy to do. These days you can very easily
either prompt your &lt;span class="caps"&gt;IDE&lt;/span&gt; or develop an agent, who reads contributing guidelines of
a project, finds an issue, and comments with the plan to fix. Or even, given a
link to an issue, generate a &amp;#8220;solution&amp;#8221; and submit a pull request (&lt;span class="caps"&gt;PR&lt;/span&gt;).&lt;/p&gt;
&lt;p&gt;One of the challenges we&amp;#8217;ve been having as maintainers, is dealing with &lt;span class="caps"&gt;LLM&lt;/span&gt;
generated comments showing their intent to work on an issue, auto generated
issues, and low quality, &lt;span class="caps"&gt;LLM&lt;/span&gt; generated PRs. These come almost exclusively from
&amp;#8220;first time contributors&amp;#8221; who seem to want to have a contribution in our project
w/o understanding their submissions. The issue has gotten so bad that at times
almost every second issue on our main repo gets at least one such message, in
many cases multiple ones. In most cases, if they had read the issue thread,
they&amp;#8217;d notice that it&amp;#8217;s not ready for contributions in the first&amp;nbsp;place.&lt;/p&gt;
&lt;h1 id="ai-generated-contributions"&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; Generated Contributions&lt;a class="headerlink" href="#ai-generated-contributions" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The interactions we have with users who post &lt;span class="caps"&gt;LLM&lt;/span&gt; generated content have a few
different&amp;nbsp;forms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New Issues&lt;/strong&gt;: We&amp;#8217;ve seen &lt;span class="caps"&gt;AI&lt;/span&gt; generated issues, sometimes multiple issues at
  once. Although at first some maintainers were willing to engage, soon we
  realised they&amp;#8217;re mostly bogus, and us spending a significant amount of time to
  check whether they&amp;#8217;re legit or not is not worth it. Especially when you take
  into account that those issues are not coming from a real use-case, and are
  purely generated by &lt;span class="caps"&gt;AI&lt;/span&gt;. Therefore even if they&amp;#8217;re a real issue, nobody&amp;#8217;s asked
  for&amp;nbsp;it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New Pull Requests&lt;/strong&gt;: The number of seemingly &lt;span class="caps"&gt;AI&lt;/span&gt; generated PRs has gone up
  substantially. When it&amp;#8217;s rather clear to us that the &lt;span class="caps"&gt;PR&lt;/span&gt; is generated by &lt;span class="caps"&gt;AI&lt;/span&gt;,
  it&amp;#8217;s easier to close it, and even block the user from the GitHub org. However,
  that takes maintainer time and attention, and not all &lt;span class="caps"&gt;AI&lt;/span&gt; generated PRs are
  clearly &lt;span class="caps"&gt;AI&lt;/span&gt; generated. In many cases, if not most, we realise/guess it&amp;#8217;s &lt;span class="caps"&gt;AI&lt;/span&gt;
  generated since the submitter simply ghosts the contribution and never
  responds to reviews. At that point, a reviewer has already spent substantial
  time reviewing and leaving helpful&amp;nbsp;comments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;PR&lt;/span&gt; Reviews&lt;/strong&gt;: Sometimes people (almost always first time contributors) leave
  reviews on PRs that are generated by &lt;span class="caps"&gt;AI&lt;/span&gt;. These are a bit easier for us to
  detect and mark as spam, but they confuse the original &lt;span class="caps"&gt;PR&lt;/span&gt; submitter if we
  don&amp;#8217;t get to them fast enough. I&amp;#8217;ve even seen conversations between the &lt;span class="caps"&gt;PR&lt;/span&gt;
  submitter and a reviewer where it&amp;#8217;s clear the submitter is talking to an &lt;span class="caps"&gt;AI&lt;/span&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Comments on Issues&lt;/strong&gt;: There are two types of &lt;span class="caps"&gt;AI&lt;/span&gt; related comments we need to
  moderate these&amp;nbsp;days:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First are the kind trying to solve the submitter&amp;#8217;s problem, or to give
  advice on how to proceed. Similar to &lt;span class="caps"&gt;PR&lt;/span&gt; reviews, they can be very
  confusing and directing contributors towards a wrong direction. We&amp;#8217;ve even
  had cases where it seems two &lt;span class="caps"&gt;AI&lt;/span&gt; agents are talking to one another, and
  after blocking those users and hiding their comments as spam, most of a
  long issue thread is&amp;nbsp;gone.&lt;/li&gt;
&lt;li&gt;Second are the ones trying to &amp;#8220;grab&amp;#8221; the issue for themselves to solve and
  submit a &lt;span class="caps"&gt;PR&lt;/span&gt;, since that&amp;#8217;s how we recommend people to contribute in our
  contributing guidelines. It seems people are directing their agents to
  follow the project&amp;#8217;s guidelines, and the agent mostly does. What keeps
  happening in reality, is multiple people leaving very similar comments on
  the same issue, trying to &amp;#8220;grab&amp;#8221; it, while the issue is not even triaged
  and no maintainer has had time to check if it&amp;#8217;s a real&amp;nbsp;issue.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="modelsystem-evaluation-and-dataset-creation"&gt;Model/System Evaluation and Dataset Creation&lt;a class="headerlink" href="#modelsystem-evaluation-and-dataset-creation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Sometimes interactions with &lt;span class="caps"&gt;AI&lt;/span&gt; generated content on the repo is due to an
individual, a research group, or a company trying to gather real world data by
testing their models and systems on our projects. This results in those entities
forcing those interactions on project maintainers, for free. We&amp;#8217;ve even seen
people submitting issues anonymously, and being open about the fact that it&amp;#8217;s to
gather validation data for their research paper. That&amp;#8217;s insane, to expect free
maintainer time to gather data, which is the exact thing being the bottleneck in
project development in open&amp;nbsp;source.&lt;/p&gt;
&lt;p&gt;Luckily, that trend seems to be going down and now many companies are paying
maintainers an hourly rate to gather data on a separate repo where the workflow
on the actual main repo of the project is not&amp;nbsp;affected.&lt;/p&gt;
&lt;p&gt;If you want to test your models, first ask for permission, and budget it in your
research proposal / internal budget. Maintainers do not like to have bots on
their repos w/o them explicitly enabling&amp;nbsp;them.&lt;/p&gt;
&lt;h1 id="trust-and-rapport"&gt;Trust and Rapport&lt;a class="headerlink" href="#trust-and-rapport" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A lot of open source is built on trust. We used to be able to easily trust users
that they&amp;#8217;ve built the code they&amp;#8217;re submitting. However, generating code has
become really cheap, while reviewing it is as expensive and time consuming as
it&amp;#8217;s always&amp;nbsp;been.&lt;/p&gt;
&lt;p&gt;People used to contribute to projects they like, and now many contribute to many
projects just to build a portfolio, and they&amp;#8217;re trying to reduce the cost of
building that portfolio as much as they&amp;nbsp;can.&lt;/p&gt;
&lt;p&gt;This has resulted in our default level of trust to be reduced. It changes the
way we treat first time contributors and is harming them by making their
experience less enjoyable, as well as hurting the project by losing some
potential long term&amp;nbsp;contributors.&lt;/p&gt;
&lt;h1 id="battling-the-surge"&gt;Battling the Surge&lt;a class="headerlink" href="#battling-the-surge" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;In our community&amp;nbsp;at &lt;code&gt;scikit-learn&lt;/code&gt;, this has been a central point of discussion
in the past couple of months. People don&amp;#8217;t approach the issue all the same way,
and some are more tolerant to such content than&amp;nbsp;others.&lt;/p&gt;
&lt;p&gt;Some maintainers are flagging the issues / PRs with a &amp;#8220;spam&amp;#8221; label, to come back
to them later and see if there&amp;#8217;s been a kind of activity from the original
poster convincing them it shouldn&amp;#8217;t be spammed /&amp;nbsp;banned.&lt;/p&gt;
&lt;p&gt;Some other maintainers are banning any user who seems to be using &lt;span class="caps"&gt;AI&lt;/span&gt; where the
generated code quality is not worth the review&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;GitHub also released an &lt;a href="https://github.com/github/ai-moderator"&gt;ai-moderator&lt;/a&gt;
action which uses &lt;span class="caps"&gt;AI&lt;/span&gt; to find &lt;span class="caps"&gt;AI&lt;/span&gt; generated content. We&amp;#8217;ve been discussing whether
to use it in our project or not. We might test it out, but it also doesn&amp;#8217;t seem
too hard to circumvent it, since the prompts used to detect &lt;span class="caps"&gt;AI&lt;/span&gt; generated content
are also open source and easy to include in an adversary&amp;#8217;s agent&amp;#8217;s system&amp;nbsp;prompt.&lt;/p&gt;
&lt;p&gt;Another idea has been to give first time contributors a sort of a task to
somewhat prove they&amp;#8217;re human, but that creates quite a bit of noise, and makes
the experience of people genuinely trying to contribute less&amp;nbsp;pleasant.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re also thinking of asking people to check a box when submitting issues and
PRs stating that they understand our rules of play, including our policy on &lt;span class="caps"&gt;AI&lt;/span&gt;
generated&amp;nbsp;content.&lt;/p&gt;
&lt;h1 id="use-ai-the-right-way"&gt;Use &lt;span class="caps"&gt;AI&lt;/span&gt; the Right Way!&lt;a class="headerlink" href="#use-ai-the-right-way" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;In this day and age, it would be unreasonable to expect folks not to use any &lt;span class="caps"&gt;AI&lt;/span&gt;
tools. Many of us use these tools one way or another. However, you should never
submit contributions w/o understanding what you&amp;#8217;re submitting. You should be
spending at least as much time creating your contribution, as it takes a
maintainer to review it. These are some of the ways you can engage with your &lt;span class="caps"&gt;AI&lt;/span&gt;&amp;nbsp;tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Explain codebase&lt;/em&gt; : Existing tools are rather good at explaining what a piece
  of code does, or for them to show you which parts of the codebase are relevant
  for a given task. They can substantially speed up your learning curve on an
  existing codebase. Note that there&amp;#8217;s no need for you to share these
  explanations on the issue tracker. Maintainers already know their&amp;nbsp;codebase.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Help with boilerplate&lt;/em&gt; : In many cases, there&amp;#8217;s some boilerplate code which
  needs to be written and sometimes repeated a few times in a contribution. The
  existing tools are rather good at auto-completing your code to speed up your
  development&amp;nbsp;process.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Help giving you a starting point&lt;/em&gt; : You can use your coding agents to get to
  a starting point which would give you an idea of what a solution to the
  problem might look like. However, you should never submit that generated code
  w/o understanding it and most probably, modifying it to fit the codebase&amp;#8217;s
  style and for it to be maintainable by humans. Note that sometimes this might
  actually slow you down, since very often writing code from scratch can be
  faster than fixing &lt;span class="caps"&gt;AI&lt;/span&gt; generated&amp;nbsp;code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="closing-thoughts"&gt;Closing Thoughts&lt;a class="headerlink" href="#closing-thoughts" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;All of this is wearing maintainers down, and maintainers are losing patience.
When these contributions started coming in the form of an issue or a &lt;span class="caps"&gt;PR&lt;/span&gt;, we&amp;#8217;d
welcome some and try to engage. However, as time passes the number of such posts
have increased, which also either ghost their contribution after submitting or
cannot apply reviews since they never understood the code they were submitting
in the first place. This has resulted in us, as maintainers, increasingly
feeling that engaging with those activities is wasting our time, and distracting
us from productive&amp;nbsp;work.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re somebody who&amp;#8217;s thinking of doing open source work solely based on &lt;span class="caps"&gt;AI&lt;/span&gt;
contributions w/o understanding what you&amp;#8217;re doing, please don&amp;#8217;t! You&amp;#8217;re harming
the project, and everybody who&amp;#8217;s trying to have genuine&amp;nbsp;contributions. &lt;/p&gt;
&lt;p&gt;And if you genuinely tried to have a contribution but got blocked before even
the first interaction, please know a vast majority of maintainers out there are
happy to work with you if they know it&amp;#8217;s actually you who wants to learn and
contribute! Contact them and resolve the&amp;nbsp;issue.&lt;/p&gt;</content><category term="open-source"/><category term="open-source"/><category term="maintenance"/><category term="ai"/></entry><entry><title>Remote Work - Connections - Open Source</title><link href="https://adrin.info/remote-work-connections-open-source.html" rel="alternate"/><published>2021-05-06T00:00:00+02:00</published><updated>2021-05-06T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2021-05-06:/remote-work-connections-open-source.html</id><summary type="html">&lt;p&gt;&lt;img alt="git/github" src="files/img/remote-work.png" title="Credit: https://blog.1password.com/remote-work-tips/"&gt;&lt;/p&gt;
&lt;p&gt;Image&amp;nbsp;on: &lt;code&gt;https://blog.1password.com/remote-work-tips/&lt;/code&gt;&lt;/p&gt;
&lt;h1 id="remote-work"&gt;Remote Work&lt;a class="headerlink" href="#remote-work" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I&amp;#8217;ve been working mostly remotely / from home for the past couple of years.
I&amp;#8217;ve worked in teams and with people whom I&amp;#8217;ve never met in person, and yet I
have a deep appreciation for them, and feel very …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="git/github" src="files/img/remote-work.png" title="Credit: https://blog.1password.com/remote-work-tips/"&gt;&lt;/p&gt;
&lt;p&gt;Image&amp;nbsp;on: &lt;code&gt;https://blog.1password.com/remote-work-tips/&lt;/code&gt;&lt;/p&gt;
&lt;h1 id="remote-work"&gt;Remote Work&lt;a class="headerlink" href="#remote-work" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I&amp;#8217;ve been working mostly remotely / from home for the past couple of years.
I&amp;#8217;ve worked in teams and with people whom I&amp;#8217;ve never met in person, and yet I
have a deep appreciation for them, and feel very connected with them. When I
joined my current workplace, it was during the pandemic, and people keep asking
how it is not to have been in the office or not to have met most of my work
mates in person. I get a bit puzzled by this question, cause I never met my
boss in my last work place since we were on two different continents&amp;nbsp;anyway.&lt;/p&gt;
&lt;p&gt;I have two types of experiences with distributed teams and half remote work,
and they&amp;#8217;ve taught me things that I&amp;#8217;d like to&amp;nbsp;share.&lt;/p&gt;
&lt;h2 id="open-source"&gt;Open Source&lt;a class="headerlink" href="#open-source" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we work in a distributed team, the types of connections you make are
different. For instance, I worked on scikit-learn for quite a while before I
met any of the contributors in person, and I still haven&amp;#8217;t met all of them.
This didn&amp;#8217;t mean there was no connection or no group dynamic. There are people
with whom you get along with more than others, like any other social situation.
The difference is, the dynamic is based on different things compared to when
you meet them in person everyday. In the distributed situation, most of what
you learn and know about people is what you see through their contributions;
their code you may review, the reviews they give to your code, their
documentation, their communication, etc. The point here is that you&amp;#8217;ll learn to
connect with people on different things than the coffee break conversations and
lunch break conversations, or their taste in clothing or&amp;nbsp;movies.&lt;/p&gt;
&lt;h2 id="consulting"&gt;Consulting&lt;a class="headerlink" href="#consulting" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Remote consulting is another place where you can end up meeting your customer
or colleagues only a few days every few weeks, if you do. In that setting, I
would have many conference calls and would go &amp;#8220;on site&amp;#8221; a few days every two or
three weeks. This makes the connections you build a combination of what you had
in your usual office setting, and the remote/distributed setting. However,
there is a big difference here, which is that the people who do go to the
office see each other much more frequently and talk about projects more
frequently than the ones who are working remotely. The trick there is either to
make sure to include people who are not in the office in all communication
relevant to them, or to try and have pockets of work where people can work
almost independently on them. In this setting, people have different types of
connections with their coworkers, and to me that was totally&amp;nbsp;fine.&lt;/p&gt;
&lt;h2 id="social-non-work-connections"&gt;Social Non-Work Connections&lt;a class="headerlink" href="#social-non-work-connections" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All of this means the types of connections you have with these people are
probably mostly professional. Even though it happens that you may get along
with somebody in the team and if you&amp;#8217;re in the same city or area, you may
decide to hang out in person, which has happened to me, but it&amp;#8217;s not the
default and most connections stay professional. Those few connections that you
make outside the working hours though, are gonna be really&amp;nbsp;nice.&lt;/p&gt;
&lt;p&gt;I tend to find my social connections outside work. This is another thing you
may need to learn or get used to. Like going to meetups, hikes, parties, or
whatever you are into, with people who are not your work mates. In a way it&amp;#8217;s
actually quite nice and healthy. It creates a healthy separation between your
work and personal&amp;nbsp;hours.&lt;/p&gt;
&lt;p&gt;However, for people who would like to create these connections with their
colleagues, I&amp;#8217;ve seen non-work related groups. Like DJs and hikers and all, and
it certainly works for some&amp;nbsp;folks.&lt;/p&gt;
&lt;h2 id="leadership"&gt;Leadership&lt;a class="headerlink" href="#leadership" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the corporate setting, leadership needs to understand what people do, see
their progress and how they perform. This is needed for promotions, planning,
etc. Some leads are not used to understanding what their directs are doing if
they&amp;#8217;re not in the same room or office. Leads may also not know how to connect
and talk to people when they don&amp;#8217;t have that other part of the connection which
happens in the office. It&amp;#8217;s crucial for team leads to be able to both trust,
and understand and monitor what their employees are up to. By monitor, I don&amp;#8217;t
mean in a surveillance way, more like to understand what people do, and where
they do it. For instance, if the employee works on GitHub, they should be
fluent in browsing and understanding the activities&amp;nbsp;there.&lt;/p&gt;
&lt;p&gt;If leaders fail to understand how their employees work, they can&amp;#8217;t help them
overcome their challenges and can&amp;#8217;t help them grow. They will also be seen as
ignorant when it comes to appreciating employees&amp;#8217;&amp;nbsp;work.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="headerlink" href="#conclusion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I don&amp;#8217;t think remote work is going away. We need to learn how to work with it,
and it has a lot to do with good communication. We should also think about the
difference between a distributed team and remote work. If a team is really
distributed, there is no central place for people to be remote from it. It
changes the way you think about where to put your communication, ie. online and
in a place everybody regardless of their location and timezone can&amp;nbsp;read.&lt;/p&gt;</content><category term="work-culture"/><category term="work"/><category term="remote-work"/><category term="open-source"/></entry><entry><title>On Benefits of Working with an Open Source Community - Corporate Perspective</title><link href="https://adrin.info/on-benefits-of-working-with-an-open-source-community-corporate-perspective.html" rel="alternate"/><published>2021-02-19T00:00:00+01:00</published><updated>2021-02-19T00:00:00+01:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2021-02-19:/on-benefits-of-working-with-an-open-source-community-corporate-perspective.html</id><summary type="html">&lt;p&gt;&lt;img alt="git/github" src="files/img/people_remote_teams_world.png" title="Credit: https://opensource.com"&gt;&lt;/p&gt;
&lt;p&gt;Image&amp;nbsp;by: &lt;code&gt;opensource.com&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This post is about how a team or project can benefit from engaging with open
source communities related to that project. There are countless, much better,
and incredible resources out there on the topic, but I needed to organize my
thoughts around it, and here&amp;#8217;s …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="git/github" src="files/img/people_remote_teams_world.png" title="Credit: https://opensource.com"&gt;&lt;/p&gt;
&lt;p&gt;Image&amp;nbsp;by: &lt;code&gt;opensource.com&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This post is about how a team or project can benefit from engaging with open
source communities related to that project. There are countless, much better,
and incredible resources out there on the topic, but I needed to organize my
thoughts around it, and here&amp;#8217;s the&amp;nbsp;result.&lt;/p&gt;
&lt;h2 id="collaborating-with-the-experts"&gt;Collaborating with the Experts&lt;a class="headerlink" href="#collaborating-with-the-experts" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One thing I do when I want to go deep in a topic, is to go and contribute to a
project related to what I want to learn. The core developers of such a library
or project together have the expertise to have such a project up and running.
That means if one starts contributing to those libraries, one will get reviewed
by those people, and that&amp;#8217;s extremely&amp;nbsp;valuable.&lt;/p&gt;
&lt;p&gt;If you continue to work on a project, and if the project is truly open and
they&amp;#8217;re happy to have new contributors on the project, that&amp;#8217;ll get you
eventually more involved and at some point your voice matters more and you can
contribute to the general direction of the project. At some point you will work
together with the other contributors and core developers on issues and projects
inside this project which are important or more relevant to&amp;nbsp;you.&lt;/p&gt;
&lt;p&gt;All of that sounds really nice, but it may not be clear what exactly it brings
to the team and company in which you work. For that, think of it from the
talent acquisition perspective. Finding the experts of the field in whatever
you do is usually not easy. And the more experts you have, the better the
quality of the product you design. Now, if we could have access to a pool of
experts in a topic and we could get their feedback and have them improve
whatever we develop, it&amp;#8217;d be pretty nice, wouldn&amp;#8217;t it? Working on a relevant
open source project can bring you exactly that. You can start working on a
topic inside that project which is more relevant to your product/goals, and
since those core developers and contributors care about what goes in the
library, they&amp;#8217;ll do their best to get your contribution to the best state to
the best of their abilities. This in effect, means you have their direct
engagement in something you need and you&amp;#8217;re working&amp;nbsp;on.&lt;/p&gt;
&lt;p&gt;This usually, but not always, applies more in libraries which are closer to the
edge of science and technology rather than the more established ones. There are
other motivations for why contributing to the more established libraries is
beneficial to your team/company in&amp;nbsp;general.&lt;/p&gt;
&lt;p&gt;To give you an example, as a part of our work on model cards at Zalando, we
need to work on a way to standardize the way we use fairness related metrics&amp;#8217;
names across our teams. The fairness community in general is still evolving
around metrics and their names and use cases, and you can see several names
referring to the same metric, or a common name which doesn&amp;#8217;t refer to any
specific metric at all. This happens to be something we also care about&amp;nbsp;in
&lt;code&gt;fairlearn&lt;/code&gt; (which is a library originally developed by people at Microsoft and
is now a community project), and therefore I&amp;#8217;d work on it to be added to our
documentation on&amp;nbsp;the &lt;code&gt;fairlearn&lt;/code&gt; side. This means I&amp;#8217;d get the feedback of all
those experts in the field who contribute to the library, before my
contribution would be added to the&amp;nbsp;documentation.&lt;/p&gt;
&lt;p&gt;When you leave your bubble, whether that be your company or your team in
academia, you realize how much brain-power is out there, and how effective
working with people from all around the world in improving your work&amp;nbsp;is!&lt;/p&gt;
&lt;h2 id="innovation"&gt;Innovation&lt;a class="headerlink" href="#innovation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is somewhat related to the previous point. The innovation as a result of
people with very different backgrounds working together is high quality and
fast. Open source may seem quite slow if you look at an individual pull request
or an issue, especially if you look at the more established projects, but even
in those projects you have changes every once in a while which change the whole
landscape. This is more pronounced in new and under development libraries
especially if you manage to have quite a few people with very different
interests and backgrounds&amp;nbsp;onboard.&lt;/p&gt;
&lt;p&gt;A couple of people living and working in the same city in the same environment,
almost never can match the creativity coming out of a group of people who live
in different continents, and work in different parts of the industry and&amp;nbsp;academia.&lt;/p&gt;
&lt;p&gt;It happens so very often that a solution which sounds pretty cool and creative
is started in a company, but very soon the project will look and feel outdated
and the new ones out there look much more attractive. Joining the forces with
the work done outside your bubble, will keep you up to date and&amp;nbsp;relevant.&lt;/p&gt;
&lt;h2 id="talent-acquisition"&gt;Talent Acquisition&lt;a class="headerlink" href="#talent-acquisition" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;People aren&amp;#8217;t going to be attracted to your team unless they know what you do
and they like it. If you work on something used by people who are your target
audience, soon they&amp;#8217;ll notice you and would like to work in a place which
contributes to their beloved tools and&amp;nbsp;ideas.&lt;/p&gt;
&lt;p&gt;If I want to add a new member to my team, it&amp;#8217;ll be much easier for me to go and
say &amp;#8220;hey, we need people, and we also work on &lt;span class="caps"&gt;XXX&lt;/span&gt; in case you were wondering&amp;#8221;,
rather than having to explain what exactly we do and how it&amp;#8217;d be interesting to
the potential&amp;nbsp;candidates.&lt;/p&gt;
&lt;p&gt;This is independent of whether you start your own open source project or if you
contribute to an existing one, and each come with their own benefits and&amp;nbsp;challenges.&lt;/p&gt;
&lt;p&gt;This is on top of the open attractive culture you create once you work openly
on projects. But bare in mind that the open source culture has many diversity
and inclusion related issues and you need to actively work on them if you want
a diverse set of people working around the project; it doesn&amp;#8217;t happen on its&amp;nbsp;own.&lt;/p&gt;
&lt;h2 id="sustainability-of-your-dependencies"&gt;Sustainability of your Dependencies&lt;a class="headerlink" href="#sustainability-of-your-dependencies" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your project depends on something, you want that thing to stay up to date
and under development. No matter how well developed a library is, if its
development is stalled, it&amp;#8217;ll be a risk to your&amp;nbsp;operations.&lt;/p&gt;
&lt;p&gt;There are many ways a company can support those dependencies, one is by
sponsoring the project to make sure maintainers stay on the project, another
one is to have employees contribute to the project and make sure it stays&amp;nbsp;active.&lt;/p&gt;
&lt;h2 id="concluding-remarks"&gt;Concluding Remarks&lt;a class="headerlink" href="#concluding-remarks" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The benefits of working with a community on open source projects aren&amp;#8217;t
necessarily obvious if you haven&amp;#8217;t really worked with them in the past. I
definitely wasn&amp;#8217;t aware of all of this before I started being more engaged with
a few communities, and I&amp;#8217;m sure there&amp;#8217;s still a ton for me to&amp;nbsp;learn.&lt;/p&gt;
&lt;p&gt;I would also like to emphasize how important the &amp;#8220;community&amp;#8221; aspect is. Having
an open source library where you&amp;#8217;re the only contributor doesn&amp;#8217;t necessarily
bring much. Most of what I talked about in this post are things you get out of
the community, not just because you work on something which is open source.
That also means you should be aware of the challenges of creating a community
or working with one. For example, you can&amp;#8217;t have a meeting behind closed doors
and then create a pull request and change something in your library. You need
to make sure anybody who comes to your repository/website, feels welcome and
included in all discussions. It also means you actually need to take those
inputs into account and keep them&amp;nbsp;engaged.&lt;/p&gt;
&lt;p&gt;Also, when engaging with an existing community, you should realize it takes a
while for them to trust you and take you more seriously. You need to work on
things they have agreed for a while, before you can start having a more
substantial influence on the&amp;nbsp;project.&lt;/p&gt;
&lt;p&gt;All in all, I truly believe being engaged with those projects is worth the
challenge and in the end you&amp;#8217;ll benefit from&amp;nbsp;it.&lt;/p&gt;</content><category term="open-source"/><category term="open-source"/></entry><entry><title>GIT/GITHUB, how to contribute to an open source project on GitHub?</title><link href="https://adrin.info/gitgithub-how-to-contribute-to-an-open-source-project-on-github.html" rel="alternate"/><published>2020-05-28T00:00:00+02:00</published><updated>2020-05-28T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2020-05-28:/gitgithub-how-to-contribute-to-an-open-source-project-on-github.html</id><summary type="html">&lt;p&gt;&lt;img alt="git/github" src="files/img/20190216-git-github.png" title="Credit: https://medium.com/cs-note/git-and-github-for-beginners-i-tutorial-263caa01f9c3"&gt;&lt;/p&gt;
&lt;p&gt;The idea behind this post is not to show how to install the tools you need, or
to list a bunch of [at a first glance seemingly&amp;nbsp;random] &lt;code&gt;git&lt;/code&gt; commands. There
are enough tutorials and blog posts explaining them out there in the wild that
with a web search you …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="git/github" src="files/img/20190216-git-github.png" title="Credit: https://medium.com/cs-note/git-and-github-for-beginners-i-tutorial-263caa01f9c3"&gt;&lt;/p&gt;
&lt;p&gt;The idea behind this post is not to show how to install the tools you need, or
to list a bunch of [at a first glance seemingly&amp;nbsp;random] &lt;code&gt;git&lt;/code&gt; commands. There
are enough tutorials and blog posts explaining them out there in the wild that
with a web search you&amp;#8217;ll find too many of them&amp;nbsp;anyway.&lt;/p&gt;
&lt;p&gt;This goal of this post is to give you the ingredients you need, to contribute
to a project on the GitHub platform and collaborate with other people&amp;nbsp;there.&lt;/p&gt;
&lt;p&gt;The first important point is the distinction between &lt;strong&gt;git&lt;/strong&gt; and &lt;strong&gt;GitHub&lt;/strong&gt;!
GitHub is a platform which&amp;nbsp;uses &lt;code&gt;git&lt;/code&gt;, but it&amp;#8217;s also not the only platform that
uses it. Another somewhat similar platform is &lt;strong&gt;GitLab&lt;/strong&gt;, but there are crucial
differences between the two that has made GitHub a much more convenient place
for a community of strangers to work together. By far the best source of
information I can recommend is the &lt;a href="https://git-scm.com/book/en/v2"&gt;Pro Git
book&lt;/a&gt;. To keep it practical, I may not strictly
stick to the definitions present in the book; the idea is to get you started
first, then you can cover the concepts more &lt;em&gt;accurately&lt;/em&gt; once you have more&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git&lt;/code&gt; is a version control system, which&amp;nbsp;is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Version control is a system that records changes to a file or set of files
over time so that you can recall specific versions later&lt;sup id="fnref:f1"&gt;&lt;a class="footnote-ref" href="#fn:f1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Strictly speaking, to develop a package&amp;nbsp;using &lt;code&gt;git&lt;/code&gt; there is no need for any
server or a platform.&amp;nbsp;Most &lt;code&gt;git&lt;/code&gt; related tasks you&amp;#8217;d be doing are done
completely locally on your own machine&amp;nbsp;anyway.&lt;/p&gt;
&lt;p&gt;The main issue at the beginning when you start to work&amp;nbsp;with &lt;code&gt;git&lt;/code&gt; is all the
jargon used around it. To get an idea of what we&amp;#8217;re talking about here, the
&lt;a href="https://www.youtube.com/watch?v=3a2x1iJFJWc"&gt;&lt;span class="caps"&gt;GIT&lt;/span&gt; Workflow - Georgia Tech - Software Development
Process&lt;/a&gt; short video is a great
place to&amp;nbsp;start:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=3a2x1iJFJWc" title="GIT Workflow - Georgia Tech - Software Development Process"&gt;&lt;img alt="GIT Workflow - Georgia Tech - Software Development
Process" src="http://img.youtube.com/vi/3a2x1iJFJWc/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now let&amp;#8217;s go through some of the concepts you&amp;#8217;d encounter in
almost any project. For the rest of this post, I&amp;#8217;ll be assuming you&amp;#8217;ve&amp;nbsp;installed &lt;code&gt;git&lt;/code&gt; and gone through &lt;a href="https://medium.com/cs-note/git-and-github-for-beginners-i-tutorial-263caa01f9c3"&gt;this
tutorial&lt;/a&gt;
up to Step 3: setup &amp;#8220;config&amp;#8221;, and know your way around a &lt;em&gt;shell/terminal&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Source tree&lt;/em&gt; is your project&amp;#8217;s folder, with all its subfolders and files that
are included in the project.&amp;nbsp;Using &lt;code&gt;git&lt;/code&gt; you&amp;#8217;ll be keeping track of all the
changes on the source&amp;nbsp;tree.&lt;/p&gt;
&lt;p&gt;However, there are always files and folders which you don&amp;#8217;t want to keep track
of, for instance&amp;nbsp;the &lt;code&gt;build&lt;/code&gt; directory which keeps compiled binary files of
your project. Cache and temporary files are also another category of files you
would like to exclude from being tracked. The way you&amp;nbsp;tell &lt;code&gt;git&lt;/code&gt; to ignore
those is through&amp;nbsp;a &lt;code&gt;.gitignore&lt;/code&gt; file usually put in the root of the project&amp;#8217;s
folder. For most programming languages, there are&amp;nbsp;descent &lt;code&gt;.gitignore&lt;/code&gt;
templates, for instance you can take a look at the
&lt;a href="https://github.com/github/gitignore/blob/master/Python.gitignore"&gt;Python.gitignore&lt;/a&gt;.
This&amp;nbsp;means &lt;code&gt;git&lt;/code&gt; will not automatically start tracking any of the files and/or
folders mentioned&amp;nbsp;in &lt;code&gt;.gitignore&lt;/code&gt;, but you can still explicitly tell it to do
so if you wish for a particular file or folder. For instance, you may want to
ignore&amp;nbsp;all &lt;code&gt;.pdf&lt;/code&gt; files, but keep a&amp;nbsp;single &lt;code&gt;.pdf&lt;/code&gt; in your repository for some
reason. You would be able to do so by explicitly&amp;nbsp;telling &lt;code&gt;git&lt;/code&gt; to keep track of&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;Once you start tracking changes to your project&amp;#8217;s source tree&amp;nbsp;using &lt;code&gt;git&lt;/code&gt;, you
have a &lt;em&gt;git repository&lt;/em&gt;. The git repository includes all the history of the
whole project in&amp;nbsp;a &lt;code&gt;.git&lt;/code&gt; folder under the root of the project. It&amp;#8217;s worth
noting that by default, every file and folder starting with a dot&amp;nbsp;(&lt;code&gt;.&lt;/code&gt;) is a
&lt;em&gt;hidden&lt;/em&gt; file/folder under&amp;nbsp;linux.&lt;/p&gt;
&lt;p&gt;For the rest of this post, I&amp;#8217;ll be using the screenshots taken at the time of
writing the post. It may slightly change through time as GitHub continues its&amp;nbsp;development.&lt;/p&gt;
&lt;p&gt;For the purpose of this tutorial, I&amp;#8217;ve setup an example repository on GitHub,
which you can see under &lt;a href="https://github.com/github-tutorials/example-repo"&gt;this
link&lt;/a&gt;. At first it&amp;#8217;s almost
empty and it looks like&amp;nbsp;this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="git/github" src="files/img/git/initial-orig.png"&gt;&lt;/p&gt;
&lt;p&gt;A few things to notice here&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There&amp;#8217;s a &lt;em&gt;Watch/Unwatch&lt;/em&gt; button which takes a few states, and you can use it
  to set the amount of notification you&amp;#8217;d be receiving for the repository. You
  will receive a notification (depending on your settings, it can be an email)
  for each event happening on the repository. If you&amp;#8217;d like to be informed and
  notified of every single post and contribution on the repo, then you&amp;#8217;d want
  to &amp;#8220;&lt;em&gt;watch&lt;/em&gt;&amp;#8221; it. For a busy repository like &lt;em&gt;scikit-learn&lt;/em&gt;, it can be tens of
  emails a day. By default, you&amp;#8217;ll be notified if there&amp;#8217;s a response to the
  issues and pull requests you&amp;#8217;ve been working on (we&amp;#8217;ll get to them&amp;nbsp;shortly).&lt;/li&gt;
&lt;li&gt;If you like to make the contributors and maintainers of the repository happy,
  you should consider &amp;#8220;&lt;em&gt;Star&lt;/em&gt;&amp;#8220;ing the&amp;nbsp;repo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The other option up there, is &lt;strong&gt;fork&lt;/strong&gt;, which requires a bit of an explanation.
When you have a git repository, you can &lt;strong&gt;clone&lt;/strong&gt; that by copying everything
you have on that repo, including&amp;nbsp;the &lt;code&gt;.git&lt;/code&gt; folder. So copying is the simplest
type of clone you can have. The clone is the same as the original repository,
including its history (since you copied&amp;nbsp;the &lt;code&gt;.git&lt;/code&gt; folder as well). But let say
you want to clone a repository from a server, and every now and then sync your
local copy with what you have on the server. That&amp;#8217;s why you also have a &amp;#8220;clone
or download&amp;#8221; button on your repository, which gives you the address of the
repository which you can use locally to clone using&amp;nbsp;a &lt;code&gt;git&lt;/code&gt; command. Here&amp;#8217;s how
you could get the address on the original&amp;nbsp;repository:&lt;/p&gt;
&lt;p&gt;&lt;img alt="git/github" src="files/img/git/git-clone-orig.png"&gt;&lt;/p&gt;
&lt;p&gt;And then you&amp;#8217;d be using the following command to clone that repository&amp;nbsp;locally:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/github-tutorials/example-repo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above command will download the repository and put it in a folder named the
same as the repo itself&amp;nbsp;(&lt;code&gt;example-repo&lt;/code&gt; in this case). At the same time, it
will store the information about from where it got the repository, which is
called a &lt;strong&gt;remote&lt;/strong&gt;, and by default this remote is called &lt;em&gt;origin&lt;/em&gt;. You can get
a list of your remotes using the following command (after going to your repo&amp;#8217;s&amp;nbsp;folder):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;example-repo
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;remote&lt;span class="w"&gt; &lt;/span&gt;-v
origin&lt;span class="w"&gt;  &lt;/span&gt;https://github.com/github-tutorials/example-repo.git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin&lt;span class="w"&gt;  &lt;/span&gt;https://github.com/github-tutorials/example-repo.git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Again, please note that the above command and all the ones from this point
should be run when you&amp;#8217;re already in your repository&amp;#8217;s folder. As you can see,
there are two identical addressed for two purposes, &lt;em&gt;fetch&lt;/em&gt; and &lt;em&gt;push&lt;/em&gt;. You can
&lt;em&gt;fetch&lt;/em&gt; changes on the repository which have happened on the &lt;em&gt;remote&lt;/em&gt; server,
but you don&amp;#8217;t have,&amp;nbsp;using &lt;code&gt;git fetch&lt;/code&gt;, and &lt;em&gt;push&lt;/em&gt; any changes on your local
machine&amp;nbsp;using &lt;code&gt;git push&lt;/code&gt;. But there are a few steps before we can do&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;You may have noticed that we cloned the repository, without telling a
maintainer of the original repo that we&amp;#8217;re doing so. That&amp;#8217;s because the repo is
a &lt;em&gt;public repository&lt;/em&gt;. For a &lt;em&gt;private repository&lt;/em&gt; you need to be given explicit
permissions by a maintainer/package developer before you can access it.
Basically if you see a repository on GitHub, you can clone&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;However, since you&amp;#8217;re not given explicit permissions, you cannot modify
anything on the original repo, and that also means you cannot do&amp;nbsp;a &lt;code&gt;git push&lt;/code&gt;
directly to it. That&amp;#8217;s why you need to &lt;strong&gt;fork&lt;/strong&gt; the repository before cloning
it. It&amp;#8217;ll create a server side clone of the repo in your account. You can do
that by simply pushing the &amp;#8220;&lt;em&gt;fork&lt;/em&gt;&amp;#8221; button up there. Please note that if you&amp;#8217;re
a member of one or more organizations, it&amp;#8217;ll ask you to choose an organization
where it should create the fork. Your username will be listed there and you
can choose that to create the fork under your own user and not touch any of the
organizations you&amp;#8217;re a member of. Otherwise it&amp;#8217;ll simply create the fork under
your username. This is what you&amp;#8217;ll see once you fork the&amp;nbsp;repo:&lt;/p&gt;
&lt;p&gt;&lt;img alt="git/github" src="files/img/git/initial-fork.png"&gt;&lt;/p&gt;
&lt;p&gt;As you can see, it also tells you from where you forked the repository. Now you
have administrative access to this repository, and that&amp;#8217;s why you also see a
&amp;#8220;&lt;em&gt;Settings&lt;/em&gt;&amp;#8221; tab. Now if you try to get the clone address of this repo, it
shows you the one you own. Now you have two options, you can delete what you
had cloned, and clone a new one using the new address, which in my case would&amp;nbsp;be:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/adrinjalali/example-repo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Please note that&amp;nbsp;the &lt;code&gt;github-tutorials&lt;/code&gt; is changed&amp;nbsp;to &lt;code&gt;adrinjalali&lt;/code&gt;, my
username. But you can also manipulate your remotes and change what you have to
the new remote address, and avoid having to delete and redownload the
repository. By&amp;nbsp;convention/default, &lt;code&gt;origin&lt;/code&gt; is the remote you own and you sync
your local copy with,&amp;nbsp;and &lt;code&gt;upstream&lt;/code&gt; is the original repository you forked.
Every now and then you&amp;#8217;ll be needing to resync your repository with the changes
which have happened&amp;nbsp;on &lt;code&gt;upstream&lt;/code&gt;, to keep up with the latest changes. So,
let&amp;#8217;s first&amp;nbsp;rename &lt;code&gt;origin&lt;/code&gt; to &lt;code&gt;upstream&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;remote&lt;span class="w"&gt; &lt;/span&gt;rename&lt;span class="w"&gt; &lt;/span&gt;origin&lt;span class="w"&gt; &lt;/span&gt;upstream
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And then add the&amp;nbsp;new &lt;code&gt;origin&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;remote&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;origin&lt;span class="w"&gt; &lt;/span&gt;https://github.com/adrinjalali/example-repo.git
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;remote&lt;span class="w"&gt; &lt;/span&gt;-v
origin&lt;span class="w"&gt;  &lt;/span&gt;https://github.com/adrinjalali/example-repo.git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin&lt;span class="w"&gt;  &lt;/span&gt;https://github.com/adrinjalali/example-repo.git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
upstream&lt;span class="w"&gt;    &lt;/span&gt;https://github.com/github-tutorials/example-repo.git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
upstream&lt;span class="w"&gt;    &lt;/span&gt;https://github.com/github-tutorials/example-repo.git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you had first forked and then cloned your own repo, you&amp;#8217;d need to only add&amp;nbsp;the &lt;code&gt;upstream&lt;/code&gt; as a remote, and now you have the ingredients to do&amp;nbsp;so.&lt;/p&gt;
&lt;p&gt;Now let say you&amp;#8217;d want to find something to work on, related to this repo.
Usually (but not always), there&amp;#8217;s an issue related what you&amp;#8217;d be working on.
You can either report an issue yourself before starting a change, or you can
pick up an issue and say you&amp;#8217;d like to work on it. The &amp;#8220;&lt;em&gt;issues&lt;/em&gt;&amp;#8221; tab on the
original repository (the upstream, not yours) would be the place to start. For
instance, I&amp;#8217;ve added two issues on our example and it looks&amp;nbsp;like:&lt;/p&gt;
&lt;p&gt;&lt;img alt="git/github" src="files/img/git/issues.png"&gt;&lt;/p&gt;
&lt;p&gt;Now assume you&amp;#8217;d like to work on the &amp;#8220;Explain what this repository is&amp;#8221; issue.
It states what should be done, and you can leave a comment saying you&amp;#8217;ll fix
it. It&amp;#8217;ll be different for you since you&amp;#8217;re not a member/maintainer of the
repo, but it&amp;#8217;ll look similar to this&amp;nbsp;one:&lt;/p&gt;
&lt;p&gt;&lt;img alt="git/github" src="files/img/git/issue-1.png"&gt;&lt;/p&gt;
&lt;p&gt;Please also note that on the right side of the title of the issue, and in the
&lt;span class="caps"&gt;URL&lt;/span&gt; of the issue, the &lt;span class="caps"&gt;ID&lt;/span&gt; of the issue is mentioned, which is 1 in this case
(the first issue in the repository); we&amp;#8217;ll get back to it&amp;nbsp;later.&lt;/p&gt;
&lt;p&gt;Going back to your local copy of the repo, you can start contributing using a
&lt;em&gt;git workflow&lt;/em&gt;, which involves proper &lt;em&gt;branching&lt;/em&gt; and &lt;em&gt;merging&lt;/em&gt; and so on.
There are different ways you can do that, and with a quick search you&amp;#8217;ll find
proposals such as &lt;a href="https://sandofsky.com/blog/git-workflow.html"&gt;this&lt;/a&gt;,
&lt;a href="https://www.atlassian.com/git/tutorials/comparing-workflows"&gt;this&lt;/a&gt;, and
&lt;a href="https://nvie.com/posts/a-successful-git-branching-model/"&gt;this&lt;/a&gt; one. It&amp;#8217;s good
to go through some of those and familiarize yourself with the process, but it&amp;#8217;s
not a must. Those workflows become more important if a few collaborators start
working on the same repository, which would happen in an organization and
specially on a GitLab platform. However, since you&amp;#8217;ll be doing everything on
your own repository and not the upstream, you can do whatever you want without
disturbing the &lt;em&gt;upstream&lt;/em&gt;. Something they all have in common is the concept of
a &lt;strong&gt;branch&lt;/strong&gt;. As &lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell"&gt;the book has
it&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nearly every &lt;span class="caps"&gt;VCS&lt;/span&gt; [(Version Control System)] has some form of branching
support. Branching means you diverge from the main line of development and
continue to do work without messing with that main line. In many &lt;span class="caps"&gt;VCS&lt;/span&gt; tools,
this is a somewhat expensive process, often requiring you to create a new
copy of your source code directory, which can take a long time for large&amp;nbsp;projects.&lt;/p&gt;
&lt;p&gt;Some people refer to Git’s branching model as its “killer feature,” and it
certainly sets Git apart in the &lt;span class="caps"&gt;VCS&lt;/span&gt; community. Why is it so special? The way
Git branches is incredibly lightweight, making branching operations nearly
instantaneous, and switching back and forth between branches generally just
as fast. Unlike many other VCSs, Git encourages workflows that branch and
merge often, even multiple times in a day. Understanding and mastering this
feature gives you a powerful and unique tool and can entirely change the way
that you&amp;nbsp;develop.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The main branch is&amp;nbsp;always &lt;code&gt;master&lt;/code&gt;. Another main branch in a project may&amp;nbsp;be
&lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;devel&lt;/code&gt;,&amp;nbsp;or &lt;code&gt;develop&lt;/code&gt;, but not all projects have it, and it depends on
the kind of &lt;em&gt;workflow&lt;/em&gt; they choose to follow. If they choose to&amp;nbsp;have &lt;code&gt;master&lt;/code&gt;
very stable and corresponding to the latest release, then the main development
would happen&amp;nbsp;on &lt;code&gt;develop&lt;/code&gt;. On the other hand, if they decide to have release
branches and have the main development happen&amp;nbsp;on &lt;code&gt;master&lt;/code&gt;, they&amp;#8217;ll probably not
have&amp;nbsp;the &lt;code&gt;develop&lt;/code&gt; branch and instead have branches such&amp;nbsp;as &lt;code&gt;v1.2&lt;/code&gt;, &lt;code&gt;v1.3&lt;/code&gt;,
etc. You usually would need to &lt;em&gt;base&lt;/em&gt; your development on the active and under
development branch. When you &lt;em&gt;fork&lt;/em&gt; or &lt;em&gt;clone&lt;/em&gt; a repository, it also includes
all the branches that repository, and you can simply change to that branch&amp;nbsp;locally.&lt;/p&gt;
&lt;p&gt;You can always see the branch you have as active&amp;nbsp;using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;status
On&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;master
nothing&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;commit,&lt;span class="w"&gt; &lt;/span&gt;working&lt;span class="w"&gt; &lt;/span&gt;tree&lt;span class="w"&gt; &lt;/span&gt;clean
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, by default you&amp;#8217;re on&amp;nbsp;the &lt;code&gt;master&lt;/code&gt; branch. Now&amp;nbsp;since &lt;code&gt;master&lt;/code&gt; is
our main development branch, you can base your work on it and create a branch
from it. You can create a branch based on your current active branch&amp;nbsp;using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;status
On&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;master
nothing&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;commit,&lt;span class="w"&gt; &lt;/span&gt;working&lt;span class="w"&gt; &lt;/span&gt;tree&lt;span class="w"&gt; &lt;/span&gt;clean
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;--list
*&lt;span class="w"&gt; &lt;/span&gt;master
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, we created a branch, but still stayed on master. In order to
change to the newly created branch, you should &lt;strong&gt;checkout&lt;/strong&gt; the&amp;nbsp;branch:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;checkout&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
Switched&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test&amp;#39;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;--list
&lt;span class="w"&gt;  &lt;/span&gt;master
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also go back&amp;nbsp;to &lt;code&gt;master&lt;/code&gt;, and safely delete&amp;nbsp;this &lt;code&gt;test&lt;/code&gt; branch:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;checkout&lt;span class="w"&gt; &lt;/span&gt;master
Switched&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;master&amp;#39;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;-D&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
Deleted&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;was&lt;span class="w"&gt; &lt;/span&gt;ea65abd&lt;span class="o"&gt;)&lt;/span&gt;.
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;--list
*&lt;span class="w"&gt; &lt;/span&gt;master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;ea65abd&lt;/code&gt; is the &lt;em&gt;abbreviated commit hash&lt;/em&gt; which you can ignore for&amp;nbsp;now.&lt;/p&gt;
&lt;p&gt;A more convenient way to create a new branch and check it out at the same time
would&amp;nbsp;be:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;checkout&lt;span class="w"&gt; &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;doc/readme
Switched&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;doc/readme&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the name of the new branch&amp;nbsp;is &lt;code&gt;doc/readme&lt;/code&gt;. The name can be
almost anything, and one convention that some people follow is to name branches&amp;nbsp;as &lt;code&gt;category/item&lt;/code&gt;, but you could as well&amp;nbsp;do &lt;code&gt;category-item&lt;/code&gt;,&amp;nbsp;or
&lt;code&gt;my-random-branch-name&lt;/code&gt;. I&amp;#8217;d suggest you always keep your master clean and in
sync with your remote, and only work on branches for each&amp;nbsp;feature/issue.&lt;/p&gt;
&lt;p&gt;Now we can finally start working on the issue. This is&amp;nbsp;the &lt;code&gt;README.md&lt;/code&gt; now:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;README.md&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="c1"&gt;# example-repo&lt;/span&gt;
example&lt;span class="w"&gt; &lt;/span&gt;repository&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;github&lt;span class="w"&gt; &lt;/span&gt;tutorials
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And let&amp;#8217;s change it&amp;nbsp;to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;README.md&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="c1"&gt;# example-repo&lt;/span&gt;
example&lt;span class="w"&gt; &lt;/span&gt;repository&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;github&lt;span class="w"&gt; &lt;/span&gt;tutorials

This&lt;span class="w"&gt; &lt;/span&gt;repository&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;made&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;showcase&lt;span class="w"&gt; &lt;/span&gt;some&lt;span class="w"&gt; &lt;/span&gt;common&lt;span class="w"&gt; &lt;/span&gt;tasks&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;processes&lt;span class="w"&gt; &lt;/span&gt;on&lt;span class="w"&gt; &lt;/span&gt;GitHub
and&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;present&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;related&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;git&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;commands.&lt;span class="w"&gt; &lt;/span&gt;The&lt;span class="w"&gt; &lt;/span&gt;post&lt;span class="w"&gt; &lt;/span&gt;explaining&lt;span class="w"&gt; &lt;/span&gt;these&lt;span class="w"&gt; &lt;/span&gt;processes
is&lt;span class="w"&gt; &lt;/span&gt;located
&lt;span class="o"&gt;[&lt;/span&gt;here&lt;span class="o"&gt;](&lt;/span&gt;gitgithub-how-to-contribute-to-an-open-source-project-on-github.html&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now let&amp;#8217;s see what the status of the local repo&amp;nbsp;is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;status
On&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;doc/readme
Changes&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;staged&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;commit:
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;use&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;what&lt;span class="w"&gt; &lt;/span&gt;will&lt;span class="w"&gt; &lt;/span&gt;be&lt;span class="w"&gt; &lt;/span&gt;committed&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;use&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;git checkout -- &amp;lt;file&amp;gt;...&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;discard&lt;span class="w"&gt; &lt;/span&gt;changes&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;working&lt;span class="w"&gt; &lt;/span&gt;directory&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;modified:&lt;span class="w"&gt;   &lt;/span&gt;README.md

no&lt;span class="w"&gt; &lt;/span&gt;changes&lt;span class="w"&gt; &lt;/span&gt;added&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;commit&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;use&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;git add&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;and/or&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;git commit -a&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, it says&amp;nbsp;the &lt;code&gt;README.md&lt;/code&gt; file is &lt;strong&gt;modified&lt;/strong&gt;. You would need to
&lt;strong&gt;add&lt;/strong&gt; the file. That brings us to the lifecycle of a file on a git repo. As
shown in &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository"&gt;the
book&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="git/github" src="files/img/git/lifecycle.png"&gt;&lt;/p&gt;
&lt;p&gt;These are the 4 states a file can have under the&amp;nbsp;repo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Untracked&lt;/em&gt;: the file exists in the project tree, but it&amp;#8217;s not being tracked
  by&amp;nbsp;git.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Unmodified&lt;/em&gt;: &lt;code&gt;git status&lt;/code&gt; won&amp;#8217;t report any of these files, since there has
  been no changes to them since the last &lt;em&gt;snapshot&lt;/em&gt; git has taken from them.
  That snapshot happens when you &lt;strong&gt;commit&lt;/strong&gt; the changes to&amp;nbsp;files.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Modified&lt;/em&gt;: the previous version of the file is recorded in the git repo, but
  since then, there has been changes to it, and these changes are not recorded&amp;nbsp;yet.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Staged&lt;/em&gt;: there has been changes to the file since the last &lt;em&gt;snapshot&lt;/em&gt;, and
  these changes are set to be recorded by a &lt;strong&gt;commit&lt;/strong&gt;, but that commit hasn&amp;#8217;t
  happened&amp;nbsp;yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A more comprehensive explanation of how to record changes in the repo can be
found
&lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So now we need to move&amp;nbsp;the &lt;code&gt;README.md&lt;/code&gt; from &lt;em&gt;modified&lt;/em&gt; to &lt;em&gt;staged&lt;/em&gt;&amp;nbsp;(using &lt;code&gt;git
add&lt;/code&gt;), and then to &lt;em&gt;unmodified&lt;/em&gt;&amp;nbsp;(using &lt;code&gt;git commit&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;README.md
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;commit&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;added required changes to the README.md&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Always include a message with the commit. Meaningful &lt;em&gt;Commit messages&lt;/em&gt; are
extremely helpful for later coming back and finding some changes you&amp;#8217;ve made
previously. Alternatively, you could summarize the above two commands in&amp;nbsp;one:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;commit&lt;span class="w"&gt; &lt;/span&gt;-am&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;added required changes to the README.md&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;doc/readme&lt;span class="w"&gt; &lt;/span&gt;b43f0b6&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;added&lt;span class="w"&gt; &lt;/span&gt;required&lt;span class="w"&gt; &lt;/span&gt;changes&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;README.md
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;changed,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;status
On&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;doc/readme
nothing&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;commit,&lt;span class="w"&gt; &lt;/span&gt;working&lt;span class="w"&gt; &lt;/span&gt;tree&lt;span class="w"&gt; &lt;/span&gt;clean
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The difference is&amp;nbsp;that &lt;code&gt;git commit -a&lt;/code&gt; adds all modified files to the staging
area, which may not be what you want. For more control you can use the two
separate commands. Also, as you can see, the working tree is &lt;em&gt;clean&lt;/em&gt;&amp;nbsp;again.&lt;/p&gt;
&lt;p&gt;Now it&amp;#8217;s time to &lt;strong&gt;push&lt;/strong&gt; the changes to our remote copy of the repository,
which we can do&amp;nbsp;by &lt;code&gt;git push&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;push
fatal:&lt;span class="w"&gt; &lt;/span&gt;The&lt;span class="w"&gt; &lt;/span&gt;current&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;doc/readme&lt;span class="w"&gt; &lt;/span&gt;has&lt;span class="w"&gt; &lt;/span&gt;no&lt;span class="w"&gt; &lt;/span&gt;upstream&lt;span class="w"&gt; &lt;/span&gt;branch.
To&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;current&lt;span class="w"&gt; &lt;/span&gt;branch&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;remote&lt;span class="w"&gt; &lt;/span&gt;as&lt;span class="w"&gt; &lt;/span&gt;upstream,&lt;span class="w"&gt; &lt;/span&gt;use

&lt;span class="w"&gt;    &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;--set-upstream&lt;span class="w"&gt; &lt;/span&gt;origin&lt;span class="w"&gt; &lt;/span&gt;doc/readme
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;span class="caps"&gt;OOPS&lt;/span&gt;, it failed, because there is no corresponding branch on the remote copy
which corresponds to the local branch we&amp;#8217;ve made. Your own remote copy is the
&lt;em&gt;upstream&lt;/em&gt; to the local copy, and you see that you need to tell git which
branch on the upstream should be the corresponding one. As you can see, by
default it suggests the same branch name, on&amp;nbsp;the &lt;code&gt;origin&lt;/code&gt; remote. The suggested
command would create a new branch on your remote copy, and upload the changes
to that&amp;nbsp;branch:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;upstream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;
&lt;span class="n"&gt;Enumerating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Counting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Delta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compression&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt;
&lt;span class="n"&gt;Compressing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Writing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;461&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;461.00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;KiB&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reused&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nl"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="nl"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pull&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GitHub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visiting&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="nl"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//github.com/adrinjalali/example-repo/pull/new/doc/readme&lt;/span&gt;
&lt;span class="nl"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="n"&gt;To&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;adrinjalali&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;
&lt;span class="n"&gt;Branch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;remote&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;branch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your output would be slightly different. Here I had to change my remote and use
the ssh connection instead. Not only it&amp;#8217;s more secure, it also allows you to
interact with your account without the need to enter your username/password
every time you need permissions. You can find the guides to setup that for your
account
&lt;a href="https://help.github.com/articles/connecting-to-github-with-ssh/"&gt;here&lt;/a&gt;. I also
recommend activating a two factor authentication (&lt;span class="caps"&gt;2FA&lt;/span&gt;) for your&amp;nbsp;account.&lt;/p&gt;
&lt;p&gt;Now if you go back to your account and check the repository, you&amp;#8217;ll see that a
new branch has been&amp;nbsp;created:&lt;/p&gt;
&lt;p&gt;&lt;img alt="git/github" src="files/img/git/github-branches.png"&gt;&lt;/p&gt;
&lt;p&gt;Now that you have the changes on your account, you can go ahead and create the
first &lt;strong&gt;pull request&lt;/strong&gt;. It basically means you&amp;#8217;d send a request to the
maintainers of the repository to pull the changes you&amp;#8217;ve made, from your repo
into the original repo. For that, you also need to specify&amp;nbsp;your &lt;code&gt;doc/readme&lt;/code&gt;
branch as the &lt;em&gt;from&lt;/em&gt; branch, and the &lt;em&gt;master&lt;/em&gt; on the original repo as the &lt;em&gt;to&lt;/em&gt;
branch. Please note that it would be the &lt;em&gt;develop&lt;/em&gt; branch on the upstream repo
if that was what you based your changes on. But in this case, we based the
changes on&amp;nbsp;the &lt;code&gt;master&lt;/code&gt; branch of the upstream&amp;nbsp;repo.&lt;/p&gt;
&lt;p&gt;Now you could click on the &amp;#8220;&lt;em&gt;Compare &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; pull request&lt;/em&gt;&amp;#8221; button, or you could go
to the upstream repository, then &lt;em&gt;Pull requests&lt;/em&gt; (&lt;span class="caps"&gt;PR&lt;/span&gt;), and then &lt;em&gt;New pull
request&lt;/em&gt;, which brings you to a page where you can explain what the does and
then create&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;Once you create the &lt;span class="caps"&gt;PR&lt;/span&gt;, you can wait for reviewers to review your &lt;span class="caps"&gt;PR&lt;/span&gt;, which
usually means they&amp;#8217;ll ask you to change a few things. To apply those changes,
you don&amp;#8217;t need to create a new &lt;span class="caps"&gt;PR&lt;/span&gt; or a new branch, you simply need to be sure
you&amp;#8217;re on the same branch as before, apply your changes, commit to your local
clone&amp;nbsp;(&lt;code&gt;git add&lt;/code&gt;, &lt;code&gt;git commit&lt;/code&gt; commands), and then push&amp;nbsp;(&lt;code&gt;git push&lt;/code&gt;). This will
add your changes to your existing &lt;span class="caps"&gt;PR&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;I hope this helps a few people a little bit. I&amp;#8217;d be happy to get some feedback
and see if it&amp;#8217;s helpful or&amp;nbsp;not.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:f1"&gt;
&lt;p&gt;Chacon, Scott, and Ben Straub. Pro git. Apress, 2014.&amp;#160;&lt;a class="footnote-backref" href="#fnref:f1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="open-source"/><category term="open-source"/></entry><entry><title>Open Source - CoC - Conflicts</title><link href="https://adrin.info/open-source-coc-conflicts.html" rel="alternate"/><published>2020-04-12T00:00:00+02:00</published><updated>2020-04-12T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2020-04-12:/open-source-coc-conflicts.html</id><summary type="html">&lt;p&gt;&lt;a href="https://www.stalawfirm.com/en/news/view/jordanian-code-of-conduct.html"&gt;&lt;img alt="CoC" src="files/img/code-of-conduct1-min.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Since I don&amp;#8217;t know individuals&amp;#8217; pronouns involved in this post, &lt;em&gt;they/them&lt;/em&gt; is
used&amp;nbsp;instead.)&lt;/p&gt;
&lt;p&gt;This post was triggered by three of PyTest maintainers leaving the project in a
single day. That&amp;#8217;s 3 out of 4-5 active developers of a project which is relied
on by a massive …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.stalawfirm.com/en/news/view/jordanian-code-of-conduct.html"&gt;&lt;img alt="CoC" src="files/img/code-of-conduct1-min.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Since I don&amp;#8217;t know individuals&amp;#8217; pronouns involved in this post, &lt;em&gt;they/them&lt;/em&gt; is
used&amp;nbsp;instead.)&lt;/p&gt;
&lt;p&gt;This post was triggered by three of PyTest maintainers leaving the project in a
single day. That&amp;#8217;s 3 out of 4-5 active developers of a project which is relied
on by a massive part of the ecosystem to test their projects/software/library.
So it really is a big deal (obviously not as big of a deal as covid19 which is
happening these days ;)&amp;nbsp;).&lt;/p&gt;
&lt;p&gt;The first person to leave was &lt;a href="https://mail.python.org/pipermail/pytest-dev/2020-April/004939.html"&gt;Bruno
Oliveira&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi&amp;nbsp;everyone,&lt;/p&gt;
&lt;p&gt;For the past years I&amp;#8217;ve been part of pytest, which is an awesome library
and also a community with awesome people. It definitely made me a better
person and better&amp;nbsp;programmer.&lt;/p&gt;
&lt;p&gt;However, the past months or so one individual has drained my will to work
on the project because of his interactions, so I decided it is best that I
leave the project for a while and focus on other&amp;nbsp;things.&lt;/p&gt;
&lt;p&gt;I of course wish the project and everyone involved the best, and will
definitely continue to work on my numerous plugins&amp;nbsp;meanwhile.&lt;/p&gt;
&lt;p&gt;Stay safe, and&amp;nbsp;cheers!&lt;/p&gt;
&lt;p&gt;Bruno&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Immediately after &lt;a href="https://mail.python.org/pipermail/pytest-dev/2020-April/004940.html"&gt;Anthony
Sottile&lt;/a&gt;
and &lt;a href="https://mail.python.org/pipermail/pytest-dev/2020-April/004941.html"&gt;Ronny
Pfannschmidt&lt;/a&gt;
left for a similar reason. It seems there have been discussions in PyTest&amp;#8217;s CoC
committee which have not come to a satisfying conclusion: judging from the fact
that two of the three developers who have stepped down are/were in PyTest&amp;#8217;s CoC
(Code of Conduct) team, one of them &lt;a href="https://github.com/pytest-dev/pytest/pull/6857"&gt;removing themself from the
committee&lt;/a&gt; and &lt;a href="https://mail.python.org/pipermail/pytest-dev/2020-April/004945.html"&gt;this
email&lt;/a&gt; by
Brianna, another member of the CoC&amp;nbsp;team:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi&amp;nbsp;all,&lt;/p&gt;
&lt;p&gt;As one of the Code of Conduct (CoC) committee members (
https://github.com/pytest-dev/pytest/blob/master/CODE_OF_CONDUCT.md ) I
want to apologise for the poor handling of issues that have led Bruno,
Anthony and Ronny to step back from the project. As a group we failed to
act decisively and now people who have contributed so much to pytest are
suffering, and for that I am&amp;nbsp;sorry.&lt;/p&gt;
&lt;p&gt;I intend to reach out to the &lt;span class="caps"&gt;PSF&lt;/span&gt; Conduct Working Group and ask them to
advise us on a way&amp;nbsp;forward.&lt;/p&gt;
&lt;p&gt;thanks,&amp;nbsp;Brianna&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;#8217;m very curious to see how it unfolds and what the &lt;span class="caps"&gt;PSF&lt;/span&gt;&amp;#8217;s CoC team thinks about
the issue, but having my CoC related experience (writing them, serving in CoC
committees, dealing with the same issues in other open source projects, etc.),
I don&amp;#8217;t think there&amp;#8217;s an easy answer to the&amp;nbsp;issue.&lt;/p&gt;
&lt;p&gt;Before talking about potential solutions, we need to understand what has been
happening. It is really important to note that &lt;strong&gt;I&amp;#8217;m not a PyTest
developer/maintainer and I&amp;#8217;m trying to understand the issue from an outsider&amp;#8217;s
perspective, and the reason I&amp;#8217;m writing this post is that this issue is by far
not unique to PyTest, and as a community we need to be better equipped to deal
with such issues&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;It seems the individual in question is &lt;a href="https://github.com/blueyed"&gt;Daniel
Hahler&lt;/a&gt; who has been very active in PyTest&amp;#8217;s
development since about &lt;a href="https://github.com/pytest-dev/pytest/graphs/contributors?from=2017-04-22&amp;amp;to=2020-04-11&amp;amp;type=c"&gt;June
2019&lt;/a&gt;.
Unfortunately, not all interactions with this person have been productive or
pleasant. As an example of an interaction which has frustrated Bruno, &lt;a href="https://twitter.com/nicoddemus/status/1248946262453424130?s=20"&gt;they
have pointed&lt;/a&gt;
to &lt;a href="https://github.com/pytest-dev/pytest/pull/6663#discussion_r375763028"&gt;this &lt;span class="caps"&gt;PR&lt;/span&gt;/comment
thread&lt;/a&gt;,
which I completely agree is a very unpleasant interaction. However, when it
comes to CoC violations, if I were in PyTest&amp;#8217;s CoC committee, I would have a
hard time deciding whether this single instance warrants banning Danial from
the project or not. Therefore I decided to dig in and see how other
interactions with them look.
&lt;a href="https://github.com/pytest-dev/pytest/pulls?q=is%3Apr+is%3Aopen+involves%3Ablueyed"&gt;Here&lt;/a&gt;
you can see the list of PRs where Daniel has been involved either as the author
or as a reviewer. A quick look at the conversations shows that clearly not all
interactions are hostile, but by looking at just the first page, I found these
examples clearly not nice:
&lt;a href="https://github.com/pytest-dev/pytest/pull/7029"&gt;this&lt;/a&gt;,
&lt;a href="https://github.com/pytest-dev/pytest/pull/6934"&gt;this&lt;/a&gt;, and &lt;a href="https://github.com/pytest-dev/pytest/pull/6840"&gt;this
one&lt;/a&gt;. One could argue that some
of the frustrations are miscommunications or cultural differences; but even
then, my judgment is that they are not constructive or respectful, at&amp;nbsp;all.&lt;/p&gt;
&lt;p&gt;Now putting all the instances together, it is very clear to me that this person
is creating an unpleasant and disrespectful environment. But does this warrant
Daniel&amp;#8217;s removal from the team? &lt;a href="https://github.com/pytest-dev/pytest/blob/master/CODE_OF_CONDUCT.md"&gt;Here&amp;#8217;s PyTest&amp;#8217;s
CoC&lt;/a&gt;, and
as examples of expected behavior it&amp;nbsp;states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Being respectful of differing viewpoints and&amp;nbsp;experiences&lt;/li&gt;
&lt;li&gt;Gracefully accepting constructive&amp;nbsp;criticism&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;And in the enforcement section, it&amp;nbsp;states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project&amp;#8217;s&amp;nbsp;leadership.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now this seems like a very clear case of violation to me, and the CoC seems to
have defined a clear consequence of those violations. Then why is this person
still on the&amp;nbsp;project?&lt;/p&gt;
&lt;p&gt;Unfortunately dealing with CoC cases is usually very complicated and in my
experience, even in cases where it seems very clear what the judgment should
be, the committee does not easily agree on a single course of action, as very
apparent from this case as well. Let&amp;#8217;s talk about some of the&amp;nbsp;reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intent vs Impact: Some would argue that the person violating the CoC did not
  &lt;em&gt;intend&lt;/em&gt; to disrespect or harass anybody, and that&amp;#8217;s more important than the
  impact the interaction has had on the disrespected/harassed person. These
  days I personally don&amp;#8217;t really agree with the argument, especially after
  reading &lt;a href="https://www.goodreads.com/book/show/4455729-35-dumb-things-well-intended-people-say"&gt;35 Dumb Things Well-Intended People Say: Surprising Things We Say
  That Widen The Diversity
  Gap&lt;/a&gt;.
  As individuals, we should be aware of the consequences and the impact of our
  actions and watch for&amp;nbsp;them.&lt;/li&gt;
&lt;li&gt;Considering the accused&amp;#8217;s position in the community: I think the most
  infamous example is &lt;a href="https://arstechnica.com/information-technology/2013/02/linus-torvalds-i-will-not-change-linux-to-deep-throat-microsoft/"&gt;Linus Trovalds&amp;#8217; many aggressive
  emails&lt;/a&gt;
  in the Linux Kernel community, and the community not reacting with an
  appropriate response. When people are in a position of power or influence, it
  makes it harder for the community or a CoC committee to act decisively. They
  don&amp;#8217;t have to be the sole owner of the
  &lt;a href="https://en.wikipedia.org/wiki/Benevolent_dictator_for_life"&gt;&lt;span class="caps"&gt;BDFL&lt;/span&gt;&lt;/a&gt; of the
  project to make it hard to deal with; being a main contributor makes it hard&amp;nbsp;enough.&lt;/li&gt;
&lt;li&gt;The accused being a peer: In many cases including this PyTest incidence, the
  accused is in a way a peer to the members of the CoC committee, who are also
  maintainers of the same project. This makes it really hard to deal with the
  case, since most people would rather try and &lt;em&gt;resolve&lt;/em&gt; the issue in one way
  or another, which does not involve banning their peer from the community.
  Most people would rather resolve the issue in the &lt;em&gt;nicest&lt;/em&gt; way&amp;nbsp;possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my experience, these [and many other] reasons prevent a candid, timely, and
decisive decision by the CoC committee. However, understanding the challenges
does not make individuals who feel strongly about the issue feel better about
the indecisiveness or lack of action, and as somebody who has been in that
position, I completely understand&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;So what can we do to improve the&amp;nbsp;situation?&lt;/p&gt;
&lt;p&gt;I believe having external people in the CoC team helps with providing an
outsider&amp;#8217;s perspective. They may have a more objective understanding of the
situation than people who are closely involved with the case. That said, many
teams may be averse to the idea since it would mean letting an &lt;em&gt;outsider&lt;/em&gt;
in the team, and in a place which is very intimate and close to the heart of
many communities. Understandably, people don&amp;#8217;t want to &lt;em&gt;give control&lt;/em&gt; to an
outsider. However, our community is larger than a single project&amp;#8217;s community,
and we could help each other out. This doesn&amp;#8217;t have to be a centralized place
like the &lt;span class="caps"&gt;PSF&lt;/span&gt; to handle all the cases (of course they can be a great place for
advice), instead it could be a group of trusted and respected people who are
rather experienced and concerned about these issues, and could sit in different
CoC&amp;nbsp;committees.&lt;/p&gt;
&lt;p&gt;Another issue is that handling CoC cases is hard, unpleasant, and is not a
trivial skill. Unfortunately in the broader community we don&amp;#8217;t really
appreciate these skills [yet] and most people are extremely inexperienced in
this regard. As a consequence, when a project appoints a CoC committee, most
probably many members of the committee have not had any experience handling CoC&amp;nbsp;cases.&lt;/p&gt;
&lt;p&gt;I remember after handling a difficult CoC case, I reached out to people who
were CoC contacts of different projects to inquire about enforceability of a
given CoC, and almost nobody had any satisfying answer. This is a result of us
as a community having no clue about how to enforce our CoCs, and sometimes the
legal challenges attached to the issue make it harder. For instance,
somebody violating a CoC may not be breaking any laws (CoC are usually more
strict than the laws of the given country), and therefore it is really tricky
to enforce that CoC in a &lt;em&gt;public&lt;/em&gt; event. This and many other related details
are not things which you can expect a usual developer in a project to know&amp;nbsp;about.&lt;/p&gt;
&lt;p&gt;As I see it, our communities have embraced having a code of conduct in one way
or another. These CoCs may not be perfect, but they&amp;#8217;re a step towards the right
direction (&lt;span class="caps"&gt;IMO&lt;/span&gt;). Then we had issues enforcing and actually implementing them,
and larger communities who have already had cases are now more equipped with
the tools they need to handle the cases. What needs to happen next, is for us
to openly talk about our cases without revealing the identities of people
involved. We should have a conversation about the details, and learn from one
another. We should also celebrate people who know how to handle these cases,
know them, and reach out for help when we&amp;#8217;re not sure what to&amp;nbsp;do.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m very happy that this incident has attracted some attention in the
community, and I hope we learn from it and keep our communities more respectful
and healthier than what they are now. Afterall, this is one of the reasons we
are not really good at diversity and inclusion in our communities and improving
on this front would help with D&amp;amp;I as&amp;nbsp;well.&lt;/p&gt;</content><category term="open-source"/><category term="community"/><category term="open-source"/></entry><entry><title>FOSDEM 2020</title><link href="https://adrin.info/fosdem-2020.html" rel="alternate"/><published>2020-02-02T00:00:00+01:00</published><updated>2020-02-02T00:00:00+01:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2020-02-02:/fosdem-2020.html</id><summary type="html">&lt;p&gt;&lt;img alt="fosdem20" src="https://fosdem.org/2020/assets/2020cake-e330eb83a6c466bcd67e7cb3291985576c4fd4f43ff954053ec0acf6c00991ab.jpg"&gt;&lt;/p&gt;
&lt;p&gt;This was my first &lt;a href="https://fosdem.org/2020/"&gt;&lt;span class="caps"&gt;FOSDEM&lt;/span&gt;&lt;/a&gt;, which has been happening
in Brussels every year for the past 20 years! It&amp;#8217;s kind of a mostly talk based
hacker space with no registration required for the attendees. This year the
estimate was 5000 attendees each day, and that doesn&amp;#8217;t include the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="fosdem20" src="https://fosdem.org/2020/assets/2020cake-e330eb83a6c466bcd67e7cb3291985576c4fd4f43ff954053ec0acf6c00991ab.jpg"&gt;&lt;/p&gt;
&lt;p&gt;This was my first &lt;a href="https://fosdem.org/2020/"&gt;&lt;span class="caps"&gt;FOSDEM&lt;/span&gt;&lt;/a&gt;, which has been happening
in Brussels every year for the past 20 years! It&amp;#8217;s kind of a mostly talk based
hacker space with no registration required for the attendees. This year the
estimate was 5000 attendees each day, and that doesn&amp;#8217;t include the fringe
events happening around the main event. The &lt;a href="https://fosdem.org/2020/fringe/"&gt;fringe
itself&lt;/a&gt; has tons of events and I managed to
attend one or&amp;nbsp;two.&lt;/p&gt;
&lt;p&gt;The whole thing has an interesting format; you have the main organization team
and then the dev rooms, all handled by volunteers, and with a perfectly
functional delegation system. The dev room volunteers have complete control
over what happens there, given a few general rules and principles like fire
safety and a&amp;nbsp;CoC.&lt;/p&gt;
&lt;p&gt;It was interesting to see that they had very few sponsors, and most sponsors
would contribute through service rather than money, &lt;em&gt;e.g.&lt;/em&gt; providing the venue,
or the cabling system or the recycled laptops to process the&amp;nbsp;videos.&lt;/p&gt;
&lt;p&gt;Another point which I&amp;#8217;d like to take to PyData conferences is that the video
review was done predominantly by speakers. I received an email after my talk, I
then suggested exact start/finish times, audio channel, etc., and with all that
your video would be up and done within an hour after your&amp;nbsp;talk.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s truly impressive to see what they&amp;#8217;ve done with volunteer work and minimal
external services. It&amp;#8217;s also interesting from a planning point of view that
they manage the whole thing w/o ever knowing who&amp;#8217;s coming and how many. Of
course there are long lines behind most of the dev room doors waiting to get
in, but usually you wouldn&amp;#8217;t wait for more than a talk&amp;#8217;s time long and that was
mostly around half an&amp;nbsp;hour.&lt;/p&gt;
&lt;p&gt;One thing which stroke me was the poor gender diversity of the conference and
the speakers. The Python room for instance, where I gave my talk, had 0 female
speakers. The diversity wasn&amp;#8217;t much better among attendees either, and it was
worse in some rooms than&amp;nbsp;others.&lt;/p&gt;
&lt;p&gt;There were two events/rooms which I particularly found interesting and met a
ton of really cool people in them were the
&lt;a href="https://chaoss.community/chaosscon-2020-eu/"&gt;CHAOScon&lt;/a&gt; and the &lt;a href="https://fosdem.org/2020/schedule/track/community_devroom/"&gt;community dev
room&lt;/a&gt;. We had really
interesting discussions and talks about how to build a community around a
project, how to measure community&amp;#8217;s health, and how to sustain it. Most
definitely useful for the communities I&amp;#8217;m involved&amp;nbsp;with.&lt;/p&gt;
&lt;p&gt;I also gave a talk on &lt;a href="https://fosdem.org/2020/schedule/event/python2020_scikit_learn_estimator/"&gt;How to write a scikit-learn compatible
estimator/transformer&lt;/a&gt;
with the
&lt;a href="https://mirrors.dotsrc.org/fosdem/2020/UA2.252A/python2020_scikit_learn_estimator.webm"&gt;video&lt;/a&gt;
and the
&lt;a href="https://github.com/adrinjalali/talks/blob/master/sklearn-estimator-fosdem-2020/custom_estimators.ipynb"&gt;material&lt;/a&gt;
both available. It was the first time I presented something (other than
opening/closing remarks of a conference) to ~500 people. It was such a pleasure
and privilege to do&amp;nbsp;so.&lt;/p&gt;
&lt;p&gt;I guess I&amp;#8217;ll try to be more engaged with the community related communities next
year if I end up going, and should definitely plan my time better. It&amp;#8217;s
overwhelming and exhausting to try and figure things out there. The talks are
also all live streamed, that&amp;#8217;s also something to&amp;nbsp;use.&lt;/p&gt;</content><category term="blog"/><category term="conference"/><category term="community"/></entry><entry><title>How we form beliefs, and implications on our beliefs regarding #metoo</title><link href="https://adrin.info/how-we-form-beliefs-and-implications-on-our-beliefs-regarding-metoo.html" rel="alternate"/><published>2020-01-15T00:00:00+01:00</published><updated>2020-01-15T00:00:00+01:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2020-01-15:/how-we-form-beliefs-and-implications-on-our-beliefs-regarding-metoo.html</id><summary type="html">&lt;p&gt;&lt;img alt="celestekidd" src="files/img/202001-celestekidd-neurips.png"&gt;&lt;/p&gt;
&lt;p&gt;This is a repost of what I posted on
&lt;a href="https://twitter.com/adrinjalali/status/1217434403044876288"&gt;twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At NeurIPS @celestekidd gave a keynote on how people form their beliefs. It was
amazing, and had two plot twists which made the audience stand and clap at the
end; something you don&amp;#8217;t see often in academic conferences. Here …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="celestekidd" src="files/img/202001-celestekidd-neurips.png"&gt;&lt;/p&gt;
&lt;p&gt;This is a repost of what I posted on
&lt;a href="https://twitter.com/adrinjalali/status/1217434403044876288"&gt;twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At NeurIPS @celestekidd gave a keynote on how people form their beliefs. It was
amazing, and had two plot twists which made the audience stand and clap at the
end; something you don&amp;#8217;t see often in academic conferences. Here&amp;#8217;s a summary,
and I love how it&amp;nbsp;ends.&lt;/p&gt;
&lt;p&gt;1/ Humans continuously form beliefs. These beliefs are constantly updated. In a
sense, our beliefs are probabilistic expectations which directly influence what
we&amp;#8217;re interested&amp;nbsp;in.&lt;/p&gt;
&lt;p&gt;Things which cause a very low, or a very high surprise level, are usually not
interesting to&amp;nbsp;us.&lt;/p&gt;
&lt;p&gt;For instance, there&amp;#8217;s a low chance that I&amp;#8217;d enjoy a book teaching the English
alphabet, or a book in a language I don&amp;#8217;t understand, and is in an alphabet I
don&amp;#8217;t know, and a topic I&amp;#8217;m not familiar with. In theory I could learn all
those things at the same time, but most probably&amp;nbsp;not.&lt;/p&gt;
&lt;p&gt;2/ Certainty diminishes interest: you&amp;#8217;re not curious about things you think you
know. Which makes sense and is reasonable; the issue is when people are certain
about certain issues when they shouldn&amp;#8217;t be. Anybody who&amp;#8217;s discussed politics
with extended family is familiar with&amp;nbsp;this&lt;/p&gt;
&lt;p&gt;Research shows it&amp;#8217;s what we think we know defines what we&amp;#8217;re interested in, and
not what we actually know. Worse: we&amp;#8217;re more inclined to reject a correct
feedback if we think we already know the [wrong] answer. but why do we have
those wrong&amp;nbsp;beliefs?&lt;/p&gt;
&lt;p&gt;3/ Certainty is driven by feedback. At least when it comes to high level
beliefs such as concepts. If there&amp;#8217;s no feedback to correct people&amp;#8217;s beliefs,
they may form one w/o proper evidence. If a belief results in correct answers
even if it&amp;#8217;s not justified, it&amp;#8217;s&amp;nbsp;reinforced.&lt;/p&gt;
&lt;p&gt;This means: if we have a belief, and we look for material online and the first
video we see agrees with that belief, it&amp;#8217;s reinforced, and that will make us be
interested in material which agree with what we now believe in, even if that
first video was factually&amp;nbsp;wrong.&lt;/p&gt;
&lt;p&gt;4/ Less feedback may encourage&amp;nbsp;overconfidence.&lt;/p&gt;
&lt;p&gt;People have different ideas of the same concept, let it be &amp;#8220;Joe Biden&amp;#8221; or &amp;#8220;a
cup&amp;#8221;, even in the same&amp;nbsp;context.&lt;/p&gt;
&lt;p&gt;Also, people tend to over estimate how many other people share their
understanding of the same&amp;nbsp;concept.&lt;/p&gt;
&lt;p&gt;5/ Humans form beliefs&amp;nbsp;quickly.&lt;/p&gt;
&lt;p&gt;Early evidence matters more than later&amp;nbsp;evidence.&lt;/p&gt;
&lt;p&gt;For instance, when it comes to &amp;#8220;activated charcoal&amp;#8221;, people go from &amp;#8220;unsure&amp;#8221; to
&amp;#8220;certain it has health benefits&amp;#8221; in two or three clicks and a few very short&amp;nbsp;videos.&lt;/p&gt;
&lt;p&gt;Now we get to the interesting&amp;nbsp;conclusions:&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s no such thing as a neutral tech platform: not Facebook, not Google, not
anyone else. Any platform showing content to users, sorts and filters content
for them resulting in forming different beliefs in different&amp;nbsp;people.&lt;/p&gt;
&lt;p&gt;Optimizing for engagement on these platforms means we&amp;#8217;re trying to keep users
on a given platform for longer, and that&amp;#8217;s through showing them what they
enjoy, which means enforcing what people already believe in and are interested
in, rather than changing or correcting&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;All of that is to say algorithms pushing content online have profound impact on
what we believe, which result in us making decisions, and not benign ones. With
a few clicks we may walk away being convinced that we shouldn&amp;#8217;t vaccinate our
kid, or that climate change is not&amp;nbsp;real.&lt;/p&gt;
&lt;p&gt;The best part: it may seem to be a scary time to be a man in tech right now.
Many men have anxiety about how to talk about gender, and how to interact with
women post #metoo. There&amp;#8217;s a sense that careers may be destroyed over awkward
passes or&amp;nbsp;misunderstandings.&lt;/p&gt;
&lt;p&gt;People do believe that men are being fired for subtle comments or minor jokes.
And this perception rightfully makes people&amp;nbsp;nervous.&lt;/p&gt;
&lt;p&gt;The issue is that this perception is not correct, and understanding how we form
beliefs, this is&amp;nbsp;why:&lt;/p&gt;
&lt;p&gt;The truth is that it takes an immense amount of mistreatment for most women to
actually complain, due to the fact that most complaints result in retaliation
and law suits cost so much money and time that most people cannot&amp;nbsp;afford.&lt;/p&gt;
&lt;p&gt;This prior should tell us that if we hear about a case, some unusually bad
behavior has happened. But why do we believe a minor&amp;nbsp;misconduct?&lt;/p&gt;
&lt;p&gt;when a harassment case becomes public, offenders almost universally apologize
for a minor fraction of the&amp;nbsp;offense.&lt;/p&gt;
&lt;p&gt;This makes people believe that they&amp;#8217;re often being prosecuted for a minor
mistreatment, and makes those reportings seem unreasonable or even&amp;nbsp;unethical.&lt;/p&gt;
&lt;p&gt;This is unfair to men who are anxious and women who miss out on those
professional&amp;nbsp;interactions.&lt;/p&gt;
&lt;p&gt;And finally, 3&amp;nbsp;takes:&lt;/p&gt;
&lt;p&gt;1/ if you hear about a woman complaining around you, she&amp;#8217;s probably been
through much more than you&amp;#8217;re aware&amp;nbsp;of.&lt;/p&gt;
&lt;p&gt;if you hear about a woman having issues, chances are they&amp;#8217;re having more issues
and that&amp;#8217;s the time to ask questions and help&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;2/ when you hear a man apologizing for a misunderstanding, you should know it&amp;#8217;s
a standard response and completely predictable, no matter what happened from
sexual harassment to sexual assault, and that they&amp;#8217;re not apologizing for all
their&amp;nbsp;misconducts.&lt;/p&gt;
&lt;p&gt;3/ unless men are deeply doing wrong by women around them, they&amp;#8217;re with very
rare exceptions, incredibly&amp;nbsp;safe.&lt;/p&gt;
&lt;p&gt;They shouldn&amp;#8217;t fear being attacked for minor comments or misunderstandings,
cause that&amp;#8217;s not what&amp;#8217;s&amp;nbsp;happening.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s [false] myth propagated by harassers and&amp;nbsp;offenders.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the link for the full video: &lt;a href="https://www.youtube.com/watch?v=6qIodcz8o-Q"&gt;&lt;img alt="Celeste Kidd - NeurIPS 2019 - How to
Know" src="http://img.youtube.com/vi/6qIodcz8o-Q/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;</content><category term="ethics"/><category term="ethics"/><category term="machine-learning"/></entry><entry><title>scikit-learn sprint at Nairobi, Kenya</title><link href="https://adrin.info/scikit-learn-sprint-at-nairobi-kenya.html" rel="alternate"/><published>2019-06-25T00:00:00+02:00</published><updated>2019-06-25T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2019-06-25:/scikit-learn-sprint-at-nairobi-kenya.html</id><summary type="html">&lt;p&gt;&lt;img alt="nairobi/sklearn" src="files/img/nairobi-sklearn.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Almost a year ago, after being the co-speaker of a &amp;#8220;My first open source
contribution&amp;#8221; talk at PyData Berlin 2018, I myself became very motivated and
started actively contributing to&amp;nbsp;the &lt;code&gt;scikit-learn&lt;/code&gt; project. I was surprised to
see how much I could and had to learn to improve my contributions …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="nairobi/sklearn" src="files/img/nairobi-sklearn.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Almost a year ago, after being the co-speaker of a &amp;#8220;My first open source
contribution&amp;#8221; talk at PyData Berlin 2018, I myself became very motivated and
started actively contributing to&amp;nbsp;the &lt;code&gt;scikit-learn&lt;/code&gt; project. I was surprised to
see how much I could and had to learn to improve my contributions, and that was
after over 20 years of programming experience, 6 years of which I did mostly
Python, and several years of working in the industry. It wasn&amp;#8217;t even the first
time I was contributing to an open source project, but it was the first time I
was actively looking for issues to&amp;nbsp;fix.&lt;/p&gt;
&lt;p&gt;One of the reasons I stayed on the project, was the extremely nice and patient
attitude of the reviewers and core developers of the project, most importantly,
Joel Nothman. I felt welcomed, tutored, and guided throughout my contributions.
Of course it also required my patience, since some of the contributions would
go through a long iteration process, even though they were only a few lines of
example code. After a while I was more confident taking over some of the more
challenging tasks, and it felt more rewarding as they became more&amp;nbsp;challenging.&lt;/p&gt;
&lt;p&gt;One day in December (2018), I woke up to find an email in my inbox which said
they&amp;#8217;d like to have me as a core developer, and if I&amp;#8217;d accept. There are very
few instances in my life in which I remember such a feeling of happiness
flowing through my whole existence. I accepted with joy, and there I was with
a whole bunch of new responsibilities added to my shoulders; but the kind which
make me want to wake up in the morning to take care&amp;nbsp;of.&lt;/p&gt;
&lt;p&gt;It also happened to be the case that the core team was planning a sprint in
Paris to go be together and work on issues in person for a few days. I joined
that sprint, in February, where we worked for a whole week, 9am to 10pm more or
less. It was so stimulating that I did not realize how exhausted I had become.
When I went back home, it took me quite a few days to recover, but it was one
of the best weeks of my life, working with brilliant people from all around the
world. It was also really good for the project, since we managed to solve some
of the very long standing issues of the project, which had been open for&amp;nbsp;years.&lt;/p&gt;
&lt;p&gt;It was a while after that when I saw an email in the mailing list, asking if
somebody could give a hand for a sprint being planned in Nairobi, Kenya. It was
going to be organized by Women in Machine Learning and Data Science
(&lt;a href="http://wimlds.org/"&gt;WiMLDS&lt;/a&gt;), and since it was the combination of two things
very close to my heart (diversity and open source), I made sure to respond to
it and offer my help &lt;span class="caps"&gt;ASAP&lt;/span&gt;. Reshama Shaikh, the main organizer from the WiMLDS
side, got back to me shortly and we started planning for the sprint. What I did
&lt;span class="caps"&gt;NOT&lt;/span&gt; know, was that they were planning to fly a contributor to Nairobi to be
there in person for the sprint, which I found a very nice&amp;nbsp;surprise.&lt;/p&gt;
&lt;p&gt;I think it took around 4 months of planning which I was involved with,
including vaccination, visa, etc. I don&amp;#8217;t think we even planned the sprint in
Paris this much, but Reshama and Mariam Haji (the main organizer in Nairobi)
were both very thorough and planned everything to the last bit of it. So I flew
to Nairobi, stayed there for 2 days, and had the sprint on a Saturday. We ended
up having about 40 attendees, almost all new to open source, and by the end of
the day we had over 20 open pull requests (PRs) generated by them on that
single&amp;nbsp;day.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s so gratifying to see the joy in people&amp;#8217;s face when they open their first
&lt;span class="caps"&gt;PR&lt;/span&gt; and receive feedback from the core developers. I always love to see their
faces when they start touching the files of the package, which they&amp;#8217;ve used
till then as a user. I still remember the feeling of sending a patch for an
open source project for the first time&amp;nbsp;(before &lt;code&gt;git&lt;/code&gt; was invented), and when I
see those same feelings in new contributors faces, it pushes all the exhaustion
out of my&amp;nbsp;being.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d say it was a very successful sprint, specially since quite a few of the
contributors we had there, are still contributing and opening new PRs even
afterwards. To me, that&amp;#8217;s what a sprint for new contributors is for, to enable
them and break all the barriers they feel having in front of them, and have
them motivated enough that they continue contributing&amp;nbsp;afterwards.&lt;/p&gt;
&lt;p&gt;However, I think there are still a few things which could be improved and I&amp;#8217;m
noting them here mostly for my own future&amp;nbsp;reference.&lt;/p&gt;
&lt;p&gt;There is a trade off between how much information the instructor tries to give
to the audience, before they jump into finding issues to work on, and how much
time is left for them to contribute. I kept the introduction very short, and
just pointed them to the part of the documentation where they could follow the
instructions and start working on issues. I did that mostly because I
personally don&amp;#8217;t find those slide based talks very productive. However, I
figured most people were lost, and they were not even sure which question to
ask or where to start. What helped, was that I found a minor issue in the
documentation, and fixed it and submitted a corresponding &lt;span class="caps"&gt;PR&lt;/span&gt;, while sharing my
screen. Immediately after that it felt like the room now knows much better what
they&amp;#8217;re doing. I would have one of those ready next time, and have kind of a
hands on tutorial on&amp;nbsp;contributing, &lt;code&gt;git&lt;/code&gt;, and GitHub&amp;nbsp;instead.&lt;/p&gt;
&lt;p&gt;Another thing which I think we should improve&amp;nbsp;in &lt;code&gt;sklearn&lt;/code&gt; documentation, is
the guide for people to setup their environments. There were people who were
still trying to setup their environment and get the package to compile still at
the end of the day, and that to me is a strong hint that something could be&amp;nbsp;improved.&lt;/p&gt;
&lt;p&gt;Another point is that it was a weekend, and most core developers were either
sleeping or not at their PCs. Being the sole person trying to review the PRs as
they come and at the same time to answer the questions on-site, is almost not
manageable. I&amp;#8217;d try to coordinate with at least one other core developer to be
online during the sprint, before the sprint this&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;Overall, I loved everything related to this sprint, and I hope we get to do it
again next year&amp;nbsp;:)&lt;/p&gt;</content><category term="open-source"/><category term="open-source"/></entry><entry><title>Ways to contribute to open source projects!</title><link href="https://adrin.info/ways-to-contribute-to-open-source-projects.html" rel="alternate"/><published>2018-10-27T00:00:00+02:00</published><updated>2018-10-27T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2018-10-27:/ways-to-contribute-to-open-source-projects.html</id><summary type="html">&lt;p&gt;&lt;img alt="OpenSource" src="files/img/20181027-opensource.png"&gt;&lt;/p&gt;
&lt;p&gt;Writing code is not the only way you can contribute to an open source project.
Like any other project, there are many tasks which are not programming, but are
required to push the project forward, and many programmers are not even
necessarily good at those tasks. Think of organizing meetups …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="OpenSource" src="files/img/20181027-opensource.png"&gt;&lt;/p&gt;
&lt;p&gt;Writing code is not the only way you can contribute to an open source project.
Like any other project, there are many tasks which are not programming, but are
required to push the project forward, and many programmers are not even
necessarily good at those tasks. Think of organizing meetups, &lt;span class="caps"&gt;UI&lt;/span&gt;/&lt;span class="caps"&gt;UX&lt;/span&gt; design,
documentation, and translation as some examples. You can read more about these
&lt;a href="https://opensource.com/life/16/1/8-ways-contribute-open-source-without-writing-code"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This post is by far not an exhaustive list of what can be done, rather what I
have personally been engaged with. Let&amp;#8217;s assume you start using a piece of
software as a library in of your projects, and through time you want to get
engaged with it&amp;nbsp;more.&lt;/p&gt;
&lt;p&gt;Please always remember that many of these packages are maintained by volunteers
and they&amp;#8217;re not always immediately available to respond to your questions,
suggestions, or contributions, so be&amp;nbsp;patient.&lt;/p&gt;
&lt;p&gt;As a user, one of the first things you may do is to read the documentation of
the package (and hopefully that exists for the package you&amp;#8217;re going to use). For
most libraries out there, the documentation may be sparse, incomplete, or at
times incomprehensible. Although in some cases it may be the case that you need
to cover some background to better understand what you&amp;#8217;re reading, but in most
cases it&amp;#8217;s the documentation you&amp;#8217;re reading which is not perfect. Unfortunately,
it&amp;#8217;s not easy to convince core developers to write good and extensive
documentation, since they&amp;#8217;re mostly busy implementing new features or fixing
reported bugs and&amp;nbsp;issues.&lt;/p&gt;
&lt;p&gt;Some packages allow you to suggest an edit to the documentation on the fly, from
the browser itself, which removes the initial barrier for many to start
contributing.
&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started.html"&gt;Elasticsearch&lt;/a&gt;
is a good example. As a new user, you probably pay attention to the
documentation probably more than anybody else. Therefore you may find mistakes
or see potential easy improvements which are usually not noticed by other more
experienced users and developers. Be encouraged to suggest any change you deem
appropriate. It may be accepted immediately, or it may start a whole
conversation about a certain aspect of the software. Some of my contributions
have been as small as a punctuation, to make the sentence a bit easier to&amp;nbsp;understand.&lt;/p&gt;</content><category term="open-source"/><category term="open-source"/></entry><entry><title>How to find a good open source project for contributions?</title><link href="https://adrin.info/how-to-find-a-good-open-source-project-for-contributions.html" rel="alternate"/><published>2018-10-13T00:00:00+02:00</published><updated>2018-10-13T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2018-10-13:/how-to-find-a-good-open-source-project-for-contributions.html</id><summary type="html">&lt;p&gt;&lt;img alt="Diversity" src="files/img/foss-diversity.jpg" title="Credit: https://blog.mapbox.com/our-code-of-conduct-for-open-source-2b3a81c00c80"&gt;&lt;/p&gt;
&lt;p&gt;When looking for a project to which you&amp;#8217;d like to contribute, there are two
major aspects you may want to consider. One is the way it&amp;#8217;s released and
managed, and the other is the community around&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;The way I see the first aspect, it&amp;#8217;s like a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Diversity" src="files/img/foss-diversity.jpg" title="Credit: https://blog.mapbox.com/our-code-of-conduct-for-open-source-2b3a81c00c80"&gt;&lt;/p&gt;
&lt;p&gt;When looking for a project to which you&amp;#8217;d like to contribute, there are two
major aspects you may want to consider. One is the way it&amp;#8217;s released and
managed, and the other is the community around&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;The way I see the first aspect, it&amp;#8217;s like a spectrum. Closed source proprietary
software on one side (let say the right side), and community driven and fully 
transparent and open
sourced project on the other side (let say the left side).
And it&amp;#8217;s important to realize that different
projects are somewhere on this spectrum, and not necessarily on either of the
two ends; let aside the whole licensing issue which itself complicates matters
by another order of&amp;nbsp;magnitude.&lt;/p&gt;
&lt;p&gt;Sometimes companies &amp;#8220;release&amp;#8221; the source code of a product, or a part of a
product. Microsoft does this pretty often. You can only look at the code; you
can&amp;#8217;t run it, you can&amp;#8217;t use it, and most people won&amp;#8217;t. To me it&amp;#8217;s more like a
public relations thingy. They use it as a tool to gain reputation among the
community. I see such examples as the ones pretty close the right side of the&amp;nbsp;spectrum.&lt;/p&gt;
&lt;p&gt;Going slightly to the left side of the spectrum, there are projects which are
&amp;#8220;released&amp;#8221; as a whole, and they may even include a friendly license letting
you use it under certain conditions. They may even have a GitHub account and
dump the source code there. Some of these projects are released once, and never
maintained further, and some go through periodical releases; but they still
keep the public community mostly in dark about the development of the
new features. They usually also don&amp;#8217;t really welcome contributions from
&amp;#8220;outsiders&amp;#8221;, and that&amp;#8217;s not because they don&amp;#8217;t like contributions; it&amp;#8217;s mostly
due to the fact that they have limited amount of resources and their priorities
are dictated by the products in which these pieces of software are used. I&amp;#8217;m not
a big fan of contributing to these projects since a large part of the
conversation about the project happens within the team inside the company,
and external contributors are treated somewhat like a second order citizens to
these projects. I get the feeling that projects such as
&lt;a href="https://github.com/explosion/spaCy"&gt;spaCy&lt;/a&gt; or
&lt;a href="https://github.com/tensorflow/tensorflow"&gt;tensorflow&lt;/a&gt; are such projects. They
have an extremely slow response rate on community questions. You do get the
feeling that it&amp;#8217;s a one sided relationship, &lt;em&gt;i.e.&lt;/em&gt; they release a version,
and if you&amp;#8217;re lucky, your concerns may have been addressed in the&amp;nbsp;release.&lt;/p&gt;
&lt;p&gt;The next group of projects are the ones which are considered as a part of
&lt;a href="https://en.wikipedia.org/wiki/Free_and_open-source_software"&gt;free and open source software (&lt;span class="caps"&gt;FOSS&lt;/span&gt;)&lt;/a&gt;.
This means not only the software is free and open source, but also volunteers
are encouraged to contribute to it and help it be improved. Naturally, if you&amp;#8217;d
like to work on a project as a volunteer, these are good candidates. But even
within this category of projects, not all of them are a friendly place to
contributors. Fortunately, more and more projects are moving towards having
a proper code of conduct ensuring a harassment free environment, and probably
the most high
profile one among the recent ones is the Linux Kernel project, which recently
confronted Linus Trovalds about it and adopted a
&lt;a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8a104f8b5867c682d994ffa7a74093c54469c11f"&gt;new code of conduct&lt;/a&gt;.
It is important to realize that there&amp;#8217;s no such thing as the open source
community. The reality is that there are different communities around different
projects/topics. People&amp;#8217;s attitudes differ from community to community,
programming language to programming language,&amp;nbsp;etc.&lt;/p&gt;
&lt;p&gt;My personal experience, which admittedly doesn&amp;#8217;t necessarily project the
complete picture about any community since it&amp;#8217;s by definition subjective, has
been the&amp;nbsp;following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;C++&lt;/strong&gt; community has always been the harshest in my experience (and I know
  I&amp;#8217;m not alone having experienced that). If you ask a question there which
  sounds &lt;em&gt;stupid&lt;/em&gt; to the experts in the field, they probably would crush you by
  asking why you haven&amp;#8217;t read a &amp;#8220;proper&amp;#8221; book on C++. By that they usually
  mean the whole C++ &lt;span class="caps"&gt;ISO&lt;/span&gt;&amp;nbsp;standard.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;R&lt;/strong&gt; community was really unpleasant to interact, to the point it encouraged
  me to switch from R to Python (yeah, that is in fact why I became a python
  coder). After creating and maintaining three packages for R in &lt;span class="caps"&gt;CRAN&lt;/span&gt; and
  Bioconductor, I was kinda done with it. I need to mention that this was back
  in 2012, and a lot could have changed in these few years. I have no idea how
  the community behaves these days; and I&amp;#8217;d be delighted if I&amp;#8217;m completely wrong
  about the community&amp;nbsp;now.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; has always been nice as far as I&amp;#8217;m concerned. It is a language
  which has it&amp;#8217;s
  &lt;a href="https://www.python.org/psf/codeofconduct/"&gt;own code of conduct&lt;/a&gt;. You can
  imagine how that has influenced the whole community around&amp;nbsp;it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are a few things you can consider when checking on a [&lt;span class="caps"&gt;FOSS&lt;/span&gt;]&amp;nbsp;project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Activity&lt;/strong&gt;: Is the project under active development? When was the last
  release? How often people open issues and contribute to the project? How often
  do main developers respond to those issues? Many projects may seem pretty cool
  at the first glance, but when you dig deeper, they may be dead projects. Sure
  you can try to revive it, but that may require more dedication and time than
  what you have at&amp;nbsp;hand.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code of Conduct&lt;/strong&gt;: The presence of a code of conduct is neither a necessary
  nor a sufficient condition for a healthy atmosphere in a project, but it&amp;#8217;s a
  sign that the core developers do care about the kind of atmosphere around the
  project. Also, the more people care about codes of conducts, the more pressure
  on the projects to adopt&amp;nbsp;one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community Contributions&lt;/strong&gt;: For larger projects, you can check how open the
  community is, by checking the repository logs. There are many tools to
  visualize activity on repositories, for instance, you can check the activity
  around tensorflow
  &lt;a href="http://ghv.artzub.com/#repo=tensorflow&amp;amp;climit=100&amp;amp;user=tensorflow"&gt;here&lt;/a&gt;,
  and activity around scikit-learn
  &lt;a href="http://ghv.artzub.com/#repo=scikit-learn&amp;amp;climit=100&amp;amp;user=scikit-learn"&gt;here&lt;/a&gt;.
  You can easily notice how tensorflow has a special user called
  &lt;em&gt;tensorflow-gardener&lt;/em&gt;, and you can read about it
  &lt;a href="https://www.oreilly.com/ideas/how-the-tensorflow-team-handles-open-source-support"&gt;here&lt;/a&gt;.
  I personally prefer repositories which have a larger set of contributors
  publicly contributing to the ones hiding internal development behind a special&amp;nbsp;user.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Treating Contributors&lt;/strong&gt;: It&amp;#8217;s never pleasant to work with a bunch of snobs!
  As a new contributor, you are bound to make many mistakes, or try things the
  way which is not the common way it&amp;#8217;s done in the project you&amp;#8217;re working on.
  This is
  normal and expected as users join a community. It is very important for the
  core developers of that project to know that and treat newcommers nicely
  and encouragingly. You can see if that&amp;#8217;s the case or not, by going through
  some of the issues and pull requests in the project you&amp;#8217;re checking. Just
  take your time and read some of the conversations happening around some of
  the issues to make sure it suits your taste. You can also check the &amp;#8220;closed&amp;#8221;
  issues
  to see how the core developers handle closing&amp;nbsp;issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In another post I&amp;#8217;ll talk about ways you can start contributing to a project
of your&amp;nbsp;choice.&lt;/p&gt;</content><category term="open-source"/><category term="open-source"/></entry><entry><title>Why would you want to contribute to an open source project?</title><link href="https://adrin.info/why-would-you-want-to-contribute-to-an-open-source-project.html" rel="alternate"/><published>2018-10-09T00:00:00+02:00</published><updated>2018-10-09T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2018-10-09:/why-would-you-want-to-contribute-to-an-open-source-project.html</id><summary type="html">&lt;p&gt;&lt;img alt="OpenSource" src="files/img/open-source-bart.jpg"&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been a fan of open source software for a long time. However, up until
recently, I wasn&amp;#8217;t seriously contributing to any specific project; but why
would you want to contribute to an open source project in the first&amp;nbsp;place?&lt;/p&gt;
&lt;p&gt;There are a few different aspects to be …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="OpenSource" src="files/img/open-source-bart.jpg"&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been a fan of open source software for a long time. However, up until
recently, I wasn&amp;#8217;t seriously contributing to any specific project; but why
would you want to contribute to an open source project in the first&amp;nbsp;place?&lt;/p&gt;
&lt;p&gt;There are a few different aspects to be taken into account here, and here I try
to go through some of&amp;nbsp;them.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Help the community&lt;/strong&gt; by contributing to the project. This is the one which
   comes to one&amp;#8217;s mind the most. You like a product, or a community around a
   particular software, hence you contribute to that particular software. Doing
   so, you help yourself (if you use the software) and everybody else who uses
   that same&amp;nbsp;product.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Help the larger community&lt;/strong&gt; by advocating and normalizing open source
   contributions. When you contribute to open source projects, you become yet
   another person who does that and it demystifies open source contributions
   for people around you. Many people (if not most) think you need to be a
   proficient programmer for an open source contributions, not realizing many
   contributions are not even in the form of code. If you work in a place where
   you use those projects in your products, it would make you and your
   colleagues realize how much work goes into those projects, and how your 
   company could benefit from spending time improving it as a part of your&amp;nbsp;job.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personal recognition&lt;/strong&gt; due to those contributions. Although your first
   contributions may be small, they&amp;#8217;ll grow and become more substantial if you
   stay persistent in your contributions. Sooner or later you become a core
   member of the community you work with, and you&amp;#8217;ll be recognized as such.
   Unlike your contributions to the closed source products in whatever company
   you work, the open source contributions are out there and you don&amp;#8217;t ever
   need to prove that you&amp;#8217;ve done them. It becomes a provable part of your
   professional&amp;nbsp;portfolio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Free mentors&lt;/strong&gt; while your contribution gets reviewed. This is only true
   for the friendly and nice project communities, and fortunately their number
   is growing. For quite a few years, if not decades, open source communities
   were mostly toxic, but that&amp;#8217;s changing and people are becoming nicer and
   more patient with newcomers. This means you shouldn&amp;#8217;t fear contributing,
   since the core developers of the project would help you go through the
   process and get your contribution up to the standards of the project. This
   also helps you gain experience working in a larger and more diverse team,
   and feel all the perks and challenges that come with&amp;nbsp;it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unfortunately not many places encourage their employees and colleagues to
have open source contributions, but still, I don&amp;#8217;t know of a place which would
dislike a candidate who has had some contributions which they can see and check.
Maybe half the job offers I get are because of my presence in the open source&amp;nbsp;world.&lt;/p&gt;
&lt;p&gt;Personally, I don&amp;#8217;t accept a job offer which involves no open source
contributions, and I always check what contributions the company and their
employees have. At least in Berlin, the scene is changing fast, and it&amp;#8217;s
becoming somewhat embarrassing for companies not to have any open source
product, and many of them are working on improving on this front. This is partly
due to the fact that many developers prefer an open and transparent company,
and open source is just a part of&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;So at the end, the more people contribute to these projects, the more pressure
it puts on companies to include themselves in this movement, which benefits
the larger open source software&amp;nbsp;community.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll talk about what these contributions mean, and how one could start
contributing in a separate&amp;nbsp;post.&lt;/p&gt;</content><category term="open-source"/><category term="open-source"/></entry><entry><title>VectorFight - Winning “Hacking Global Health”</title><link href="https://adrin.info/vectorfight-winning-hacking-global-health.html" rel="alternate"/><published>2017-12-06T00:00:00+01:00</published><updated>2017-12-06T00:00:00+01:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2017-12-06:/vectorfight-winning-hacking-global-health.html</id><summary type="html">&lt;p&gt;&lt;img alt="VectorFight" src="files/img/vectorfight-Winning_team-700.jpg" title="Credit: http://health.bmz.de/events/Events_2017/KfW_hackathon_innovative_urban_health_solutions/index.html"&gt;&lt;/p&gt;
&lt;h3 id="background"&gt;Background&lt;a class="headerlink" href="#background" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A weekend in October (15-17.10.2017), on the side of the
&lt;a href="https://www.worldhealthsummit.org/whs-2017.html"&gt;9th World Health Summit (&lt;span class="caps"&gt;WHS&lt;/span&gt;)&lt;/a&gt;
I attended a hackathon called
&lt;a href="https://www.kfw-entwicklungsbank.de/International-financing/KfW-Development-Bank/Topics/Health/Hacking-Global-Health/"&gt;Hacking Global Health&lt;/a&gt;.
We were nearly 40 people, in about 20 teams, and each team had to pitch an idea
in 2 minutes. The only constraint on …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="VectorFight" src="files/img/vectorfight-Winning_team-700.jpg" title="Credit: http://health.bmz.de/events/Events_2017/KfW_hackathon_innovative_urban_health_solutions/index.html"&gt;&lt;/p&gt;
&lt;h3 id="background"&gt;Background&lt;a class="headerlink" href="#background" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A weekend in October (15-17.10.2017), on the side of the
&lt;a href="https://www.worldhealthsummit.org/whs-2017.html"&gt;9th World Health Summit (&lt;span class="caps"&gt;WHS&lt;/span&gt;)&lt;/a&gt;
I attended a hackathon called
&lt;a href="https://www.kfw-entwicklungsbank.de/International-financing/KfW-Development-Bank/Topics/Health/Hacking-Global-Health/"&gt;Hacking Global Health&lt;/a&gt;.
We were nearly 40 people, in about 20 teams, and each team had to pitch an idea
in 2 minutes. The only constraint on the ideas was that it had to do with
improving health in poor urban areas. The trick was that only 8 of these teams
were supposed to go to the &amp;#8220;next&amp;#8221; round and develop those ideas for the final
pitch. But that was supposed to happen organically, without any interference
from the judges or organizers. This meant that we had around 15 minutes or so,
to form 8 teams on our own. The organizers, however, tried to push people with
different backgrounds into the same teams, such that each team has all the
required&amp;nbsp;skills.&lt;/p&gt;
&lt;p&gt;This is how I ended up in a team which needed somebody with &amp;#8220;&lt;span class="caps"&gt;IT&lt;/span&gt;&amp;#8221; background.
They were people from two different teams, one with a focus on malaria mosquito
traps, the other focusing on plague carrying rats. So I abandoned my idea, and
we joined forces to come up with something. A bit later two more joined us with
a business&amp;nbsp;background.&lt;/p&gt;
&lt;p&gt;After merging two of the ideas, we came up with a platform to educate people and
improve their situation regarding vector borne diseases. It was a fantastic
experience for me, since I didn&amp;#8217;t even know this meaning of the word &amp;#8220;vector&amp;#8221;
beforehand. Our team was fantastically open about the ideas, and that&amp;#8217;s why we
ended up with an idea which was none of the original ones, but one covering
two of the original ideas. The final pitch was so different from any of the
original pitches, that we had to resubmit a pitch form to put in the
list of final&amp;nbsp;pitches.&lt;/p&gt;
&lt;p&gt;At the end, according to the judges, it was a clear and easy decision to choose
our team as the winning team, for which we&amp;#8217;re really&amp;nbsp;proud.&lt;/p&gt;
&lt;h3 id="idea"&gt;Idea&lt;a class="headerlink" href="#idea" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The idea is a platform which gives information about vectors and their related
diseases to the users, and it receives information about those vectors from the
users and other sources such as government organizations or research institutes.
It has two different&amp;nbsp;faces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A smartphone app which enables the community to report potential breeding
   sites such as potholes and communicate with each other in order to
   potentially take action and fix them. They also receive information about
   vectors and diseases most relevant to them. The app serves both as a mean to
   disseminate information, and to collect data. It also would try to build
   a community around these&amp;nbsp;issues.&lt;/li&gt;
&lt;li&gt;A web interface/&lt;span class="caps"&gt;API&lt;/span&gt; enabling different organizations to interact with the
   platform and use the data uploaded by the users. They would get a clear
   overview of how a specific vector/disease is spreading through&amp;nbsp;time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;#8217;s an overview of the ecosystem around the&amp;nbsp;idea:&lt;/p&gt;
&lt;p&gt;&lt;img alt="ecosystem" src="files/img/vectorfight-overview.png"&gt;&lt;/p&gt;
&lt;p&gt;And the interface of the solution would&amp;nbsp;resemble:&lt;/p&gt;
&lt;p&gt;&lt;img alt="app" src="files/img/vectorfight-app.png"&gt;&lt;/p&gt;
&lt;p&gt;And &lt;a href="files/VectorFIGHT_GHP_Meeting_A_Jalali_2.pdf"&gt;here&lt;/a&gt;&amp;#8216;s the presentation,
the result of two hard working&amp;nbsp;days.&lt;/p&gt;
&lt;p&gt;After the hackathon, we presented the idea at the conference itself, and a few
days later at a German African health collaboration conference. A few months
later we were invited to present the idea during a German Health Partnership
meeting having quite a few key players of healthcare in Germany present.
Unfortunately we never got a proper backing from the public sector, and the
idea more or less died. I hope someone revives it some&amp;nbsp;day!&lt;/p&gt;</content><category term="healthcare"/><category term="hackathon"/><category term="ideas"/><category term="healthcare"/></entry><entry><title>A Criticism of “Detecting Sexual Orientation Using Neural Networks”</title><link href="https://adrin.info/a-criticism-of-detecting-sexual-orientation-using-neural-networks.html" rel="alternate"/><published>2017-10-05T00:00:00+02:00</published><updated>2017-10-05T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2017-10-05:/a-criticism-of-detecting-sexual-orientation-using-neural-networks.html</id><summary type="html">&lt;p&gt;I&amp;#8217;d like to talk about this study: &lt;a href="https://osf.io/fk3xr/"&gt;Deep neural networks are more accurate than humans at detecting sexual orientation from facial images&lt;/a&gt;, and it&amp;#8217;s not going to be a praise of the&amp;nbsp;research!&lt;/p&gt;
&lt;h2 id="damaging-message"&gt;Damaging Message&lt;a class="headerlink" href="#damaging-message" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I put this study in the same category as studies trying to argue …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I&amp;#8217;d like to talk about this study: &lt;a href="https://osf.io/fk3xr/"&gt;Deep neural networks are more accurate than humans at detecting sexual orientation from facial images&lt;/a&gt;, and it&amp;#8217;s not going to be a praise of the&amp;nbsp;research!&lt;/p&gt;
&lt;h2 id="damaging-message"&gt;Damaging Message&lt;a class="headerlink" href="#damaging-message" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I put this study in the same category as studies trying to argue women are different than men, usually in derogatory ways, e.g. proving they&amp;#8217;re weaker, less intelligent, or worse at math. Recently we had the google engineer citing a whole bunch of them to support his argument about why men are better coders, or men are better in tech, or whatever bullshit he wanted to argue for. Honestly I won&amp;#8217;t bother reading it; I mostly heard about it in podcasts and read about it in the news. My point is, those gender related studies tend to be more damaging than beneficial, and I see no point in doing them. I understand this is a very consequentialist way of assessing the value of the work, but I&amp;#8217;m comfortable with it for&amp;nbsp;now.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s the same with the study in question. What&amp;#8217;s the point of having a module predicting people&amp;#8217;s sexual orientation given a face image, other than some other people using it in an argument such as: &amp;#8220;Your face shouts you&amp;#8217;re gay, scientifically proven&amp;#8221;!!! I&amp;#8217;m sure our dear homophobes out there can think of more damaging ways of using the results of this research. This is all I could come up&amp;nbsp;with!&lt;/p&gt;
&lt;h2 id="methodology"&gt;Methodology&lt;a class="headerlink" href="#methodology" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I don&amp;#8217;t even know where to start. I&amp;#8217;ll split these points into the ones questioning the validity of the study, and the ones which are simply poor&amp;nbsp;wording.&lt;/p&gt;
&lt;h3 id="questioning-validity"&gt;Questioning Validity&lt;a class="headerlink" href="#questioning-validity" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id="auc-calculation"&gt;&lt;span class="caps"&gt;AUC&lt;/span&gt; calculation&lt;a class="headerlink" href="#auc-calculation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In a classification problem, you&amp;#8217;d use your module to predict the outcome, draw the &lt;span class="caps"&gt;ROC&lt;/span&gt;, and calculate the Area Under &lt;span class="caps"&gt;ROC&lt;/span&gt; (&lt;span class="caps"&gt;AUC&lt;/span&gt;). Pretty straightforward for a binary classification, which is the case in this paper. What I don&amp;#8217;t understand, is this randomly choosing a straight person&amp;#8217;s photo to compare against a homosexual, to calculate an &lt;span class="caps"&gt;AUC&lt;/span&gt;. I simply don&amp;#8217;t understand why you&amp;#8217;d do that, and as a result, I can&amp;#8217;t assess the performance measures reported in the&amp;nbsp;article.&lt;/p&gt;
&lt;h4 id="variance-of-the-accuracy"&gt;Variance of the accuracy&lt;a class="headerlink" href="#variance-of-the-accuracy" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;They report one &lt;span class="caps"&gt;AUC&lt;/span&gt; performance for those 20 folds. I guess the results are accumulated over 20 folds and one single &lt;span class="caps"&gt;AUC&lt;/span&gt; is calculated overall. This is important, because the calculated performance usually highly depends on the random split of the data. Therefore without a data showing the distribution of the calculated AUCs, one single number is not representative of how reliable the model in reality&amp;nbsp;is.&lt;/p&gt;
&lt;h4 id="svd-on-each-fold-separately-or-not"&gt;&lt;span class="caps"&gt;SVD&lt;/span&gt; on each fold separately or not?&lt;a class="headerlink" href="#svd-on-each-fold-separately-or-not" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;In any data analysis, it is crucial to apply [virtually all] preprocessing steps only on the training data. Otherwise you&amp;#8217;re already seeing the test data before even starting you training, and that&amp;#8217;s&amp;nbsp;cheating.&lt;/p&gt;
&lt;p&gt;The text is not clear weather they run a separate &lt;span class="caps"&gt;SVD&lt;/span&gt; for each of those 20 folds they have or not. If they do &lt;span class="caps"&gt;SVD&lt;/span&gt; once and use the same features on all those folds, the results are immediately invalid. I cannot tell from the text what they&amp;#8217;ve done, and I couldn&amp;#8217;t see a link to their source code. My guess is that they are actually doing it the right way, but it&amp;#8217;s not written&amp;nbsp;clearly.&lt;/p&gt;
&lt;h4 id="model-interpretation"&gt;Model Interpretation&lt;a class="headerlink" href="#model-interpretation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Quoting the&amp;nbsp;article:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The gender atypicality of gay faces extended beyond morphology. Gay men had less facial hair, suggesting differences in androgenic hair growth, grooming style, or both. They also had lighter skin, suggesting potential differences in grooming, sun exposure, and/or testosterone levels. Lesbians tended to use less eye makeup, had darker hair, and wore less revealing clothes (note the higher neckline), indicating less gender-typical grooming and style. Furthermore, although women tend to smile more in general (Halberstadt, Hayes, &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Pike, 1988), lesbians smiled less than their heterosexual counterparts. Additionally, consistent with the association between baseball caps and masculinity in American culture (Skerski, 2011), heterosexual men and lesbians tended to wear baseball caps (see the shadow on their foreheads; this was also confirmed by a manual inspection of individual images). The gender atypicality of the faces of gay men and lesbians is further explored in Study&amp;nbsp;2.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Comparing these factors with the reported &lt;span class="caps"&gt;AUC&lt;/span&gt;, you could argue that social trends and stereotypes followed by many people, has a substantial factor in giving the classifier its power. To better understand my point, assume you want to train a classifier predicting whether or not a person in a picture is a transgender. Since many transgender people follow an exaggerated version of the opposite gender&amp;#8217;s stereotypes in the society, and the skull itself is predictive of the sex of the person to a good extent on its own, the model would probably have an easy time giving the right&amp;nbsp;outcome.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=GHl8xvc-GCI"&gt;&lt;img alt="Skull and sex" src="http://img.youtube.com/vi/GHl8xvc-GCI/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What I mean, is that if you have a model which doesn&amp;#8217;t take into account the confound social variables to predict a certain variable, your results are&amp;nbsp;crap!&lt;/p&gt;
&lt;h3 id="poor-wording"&gt;Poor wording&lt;a class="headerlink" href="#poor-wording" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id="not-a-deep-neural-network-dnn-method"&gt;Not a Deep Neural Network (&lt;span class="caps"&gt;DNN&lt;/span&gt;) Method&lt;a class="headerlink" href="#not-a-deep-neural-network-dnn-method" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The article suggests DNNs can achieve the reported performance, while using a &lt;span class="caps"&gt;DNN&lt;/span&gt; only to extract features, and then feeding them to an &lt;span class="caps"&gt;SVD&lt;/span&gt;-&amp;gt;&lt;span class="caps"&gt;LASSO&lt;/span&gt;-&amp;gt;logistic regression pipeline. How is that a &lt;span class="caps"&gt;DNN&lt;/span&gt; method? I can only imagine they&amp;#8217;ve chosen to advertise it as such, due to the hype around deep learning; after all, who would dare to argue with a &lt;span class="caps"&gt;DNN&lt;/span&gt; these days? Basically, the statement &amp;#8220;deep neural networks can detect sexual orientation from faces&amp;#8221; is a complete misrepresentation of the&amp;nbsp;research.&lt;/p&gt;
&lt;h4 id="lasso-and-alpha"&gt;&lt;span class="caps"&gt;LASSO&lt;/span&gt; and alpha&lt;a class="headerlink" href="#lasso-and-alpha" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;They say they use &lt;span class="caps"&gt;LASSO&lt;/span&gt; with alpha=1 for feature selection. The alpha they refer to is a parameter of elastic net, not &lt;span class="caps"&gt;LASSO&lt;/span&gt;, which results in &lt;span class="caps"&gt;LASSO&lt;/span&gt; when set to 1. In other words, &lt;span class="caps"&gt;LASSO&lt;/span&gt; &lt;span class="caps"&gt;ALWAYS&lt;/span&gt; has that alpha equal to 1, otherwise it&amp;#8217;s not a &lt;span class="caps"&gt;LASSO&lt;/span&gt;.&lt;/p&gt;
&lt;h2 id="final-remarks"&gt;Final Remarks&lt;a class="headerlink" href="#final-remarks" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I guess at the writing of this post, the article has not been accepted and it may be subject to many changes; in which case, I hope reviewers find the problems I found and many more, so that the final version of the article is a much better work than what I read. But even then, I have a hard time understanding the reason behind such studies. I&amp;#8217;m sure there are much better and more beneficial ways of analyzing the same data and coming up with much better&amp;nbsp;conclusions.&lt;/p&gt;
&lt;p&gt;Also, I could only analyze this research in depth only if I had the code and the data publicly available. One may argue that I can contact the authors asking for the code and the data; but that&amp;#8217;s not what I call &amp;#8220;publicly&amp;nbsp;available&amp;#8221;!&lt;/p&gt;</content><category term="ethics"/><category term="ethics"/><category term="machine-learning"/></entry><entry><title>A Central Cancer Diagnostics Hub</title><link href="https://adrin.info/a-central-cancer-diagnostics-hub.html" rel="alternate"/><published>2017-04-18T00:00:00+02:00</published><updated>2017-04-18T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2017-04-18:/a-central-cancer-diagnostics-hub.html</id><summary type="html">&lt;p&gt;Although the context of this post is bioinformatics and cancer, it applies to many other fields as well. I&amp;#8217;ve had this idea for a while, and this an effort to make it more concrete. In this post, a method refers to a computational model or an algorithm, from the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Although the context of this post is bioinformatics and cancer, it applies to many other fields as well. I&amp;#8217;ve had this idea for a while, and this an effort to make it more concrete. In this post, a method refers to a computational model or an algorithm, from the preprocessing phase to the final&amp;nbsp;result.&lt;/p&gt;
&lt;h3 id="motivation"&gt;Motivation&lt;a class="headerlink" href="#motivation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The idea is motivated by my experience in bioinformatics, dealing with cancer data and cancer related questions such as cancer diagnostics, while being in a cancer hospital observing some of the struggles oncologists and pathologists face. I&amp;#8217;d like to address the following&amp;nbsp;challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reproducibility crisis in the field, which I talked about in more detail &lt;a href="http://adrin.info/an-essay-on-the-reproducibility-crisis.html"&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Reinventing the wheel (over and over again). In science to show the merits of your work, you most probably need to compare it with other methods. Since most methods are not open source, and even when they are, it&amp;#8217;s not a trivial task to use them on your data, you end up at least partially re-implementing those methods&amp;nbsp;yourself. &lt;/li&gt;
&lt;li&gt;The gap between research and clinics. Again, since it&amp;#8217;s not easy to use most published methods on your data, it&amp;#8217;s not easy for clinics to take a publication and use that method on patients&amp;#8217;&amp;nbsp;data.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="players"&gt;Players&lt;a class="headerlink" href="#players" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ideally there would be a place facilitating method development as well as their usage. To understand the proposed system, consider the problem of predicting the subclass of different cancer types, and the following three players or&amp;nbsp;stakeholders.&lt;/p&gt;
&lt;h4 id="the-programmer-or-the-bioinformatician"&gt;The programmer, or the bioinformatician&lt;a class="headerlink" href="#the-programmer-or-the-bioinformatician" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The system provides certain APIs for programmers to deliver tasks related to cancer diagnostics. These tasks are steps along the way of the analysis. Preprocessing of the data is one step, so is predicting the sub-class of a cancer for instance. Programmers don&amp;#8217;t have to implement the whole pipeline; they can focus on a method, for example, which relies on a certain preprocessing model which itself has already been implemented on the existing datasets. Or in contrast, a researcher can implement a preprocessing technique and test it in combination with different methods available in the repository of the&amp;nbsp;system.&lt;/p&gt;
&lt;h4 id="the-oncologist-pathologist-or-a-clinic"&gt;The oncologist, pathologist, or a clinic&lt;a class="headerlink" href="#the-oncologist-pathologist-or-a-clinic" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Once a method is uploaded to the system, it can be trained on different cancer types, and then a clinic or a hospital can use the system to get suggestions on the subclass of the cancer of a newly acquired sample for a patient. They can also check if different methods agree with each other on their prediction. The system in this case plays the role of yet another expert in the counsel diagnosing a patient, or to help an oncologist if the patient&amp;#8217;s disease is not an easy case to diagnose. In many hospitals oncologists already use the algorithms developed by the bioinformaticians working in their labs, but that&amp;#8217;s the limit they can reach and they don&amp;#8217;t have access to other labs&amp;#8217; methods. Some other clinics/cancer centers have dedicated groups re-developing published works of other labs/researchers. This diagnosis hub would be a place for them to join their&amp;nbsp;efforts.&lt;/p&gt;
&lt;h4 id="the-labperson-producing-data"&gt;The lab/person producing data&lt;a class="headerlink" href="#the-labperson-producing-data" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When a lab produces a new dataset, they usually need to analyze the data and explain how their dataset can be used and where its values are. After cleaning the data, this process involves preprocessing the data and then applying some machine learning techniques to it, to show and support a hypothesis such as &amp;#8220;measurement X is predictive of condition Y&amp;#8221;. Without a place for them to upload and apply existing methods on their data, they need a computational biologist and a fair amount of time for the analysis to happen. Instead, they could upload the dataset to this hub and have different methods run against it, and then use the methods&amp;#8217; outcomes for their&amp;nbsp;analysis.&lt;/p&gt;
&lt;h3 id="related-and-existing-work"&gt;Related and existing work&lt;a class="headerlink" href="#related-and-existing-work" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are many open datasets out there, but they are not necessarily nicely formatted and they don&amp;#8217;t follow the same guidelines to store the data. After a while, at least two efforts started to tackle this problem, one is &lt;a href="https://icgc.org/"&gt;&lt;span class="caps"&gt;ICGC&lt;/span&gt;&lt;/a&gt; in Europe, and the other one is &lt;a href="https://cancergenome.nih.gov/"&gt;&lt;span class="caps"&gt;TCGA&lt;/span&gt;&lt;/a&gt; in the &lt;span class="caps"&gt;US&lt;/span&gt;. These efforts store the data in a nicely formatted way, which makes it convenient to develop a method on one cancer type, and try it on the other ones. There are also places which have their own method run against different datasets, and you can browse their results and visualizations, or efforts and products enabling you to create your own platform and data storage. Some examples using the &lt;span class="caps"&gt;TCGA&lt;/span&gt; data are listed &lt;a href="https://cancergenome.nih.gov/abouttcga/aboutdata/analyticaltools"&gt;here&lt;/a&gt;. There are also products such as &lt;a href="https://www.dnanexus.com"&gt;DNAnexus&lt;/a&gt; which provides related services, which helps researchers move their research to the cloud and have reproducible results, but it doesn&amp;#8217;t work as a hub serving all the abovementioned&amp;nbsp;players.&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;a class="headerlink" href="#conclusion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We, as a society, need an open product and a team delivering such a service, which is easy to setup and use. I recently left academia, while still wrapping up my PhD thesis, and joined industry. I see very well where academia could use recent advancements in industry when it comes to big data and machine learning infrastructure, and also how clinics and the industry could benefit from a fast adaptation of recent academic&amp;nbsp;advances.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: I&amp;#8217;ll try to update this post as it&amp;nbsp;develops.&lt;/p&gt;</content><category term="science"/><category term="reproducibility-crisis"/><category term="ideas"/><category term="cancer"/><category term="bioinformatics"/></entry><entry><title>An Essay on the Reproducibility Crisis</title><link href="https://adrin.info/an-essay-on-the-reproducibility-crisis.html" rel="alternate"/><published>2017-04-16T00:00:00+02:00</published><updated>2017-04-16T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2017-04-16:/an-essay-on-the-reproducibility-crisis.html</id><summary type="html">&lt;h3 id="reproducibility-in-science"&gt;Reproducibility (in science)&lt;a class="headerlink" href="#reproducibility-in-science" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It&amp;#8217;s almost not a word, to the extent that as far as I know it&amp;#8217;s only used in the context of science, and it has its own &lt;a href="https://en.wikipedia.org/wiki/Reproducibility"&gt;Wikipedia page&lt;/a&gt;. In simple terms, a scientific research&amp;#8217;s results are reproducible if you can take its report …&lt;/p&gt;</summary><content type="html">&lt;h3 id="reproducibility-in-science"&gt;Reproducibility (in science)&lt;a class="headerlink" href="#reproducibility-in-science" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It&amp;#8217;s almost not a word, to the extent that as far as I know it&amp;#8217;s only used in the context of science, and it has its own &lt;a href="https://en.wikipedia.org/wiki/Reproducibility"&gt;Wikipedia page&lt;/a&gt;. In simple terms, a scientific research&amp;#8217;s results are reproducible if you can take its report, follow the instructions, and get the same or similar&amp;nbsp;results.&lt;/p&gt;
&lt;h3 id="reproducibility-crisis"&gt;Reproducibility Crisis&lt;a class="headerlink" href="#reproducibility-crisis" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Most research cannot be reproduced, see &lt;a href="https://www.scientificamerican.com/video/is-there-a-reproducibility-crisis-in-science/"&gt;this video&lt;/a&gt;, or articles like &lt;a href="http://www.nature.com/news/1-500-scientists-lift-the-lid-on-reproducibility-1.19970"&gt;this one&lt;/a&gt;, &lt;a href="https://phys.org/news/2016-12-crisis-timelinemilestones-tackling-reliability.html"&gt;this other one&lt;/a&gt;, or &lt;a href="https://www.forbes.com/sites/stevenbertoni/2017/04/11/box-ceo-aaron-levie-talks-trump-tech-and-how-to-stay-nimble-as-a-public-software-company/#27af468342b7"&gt;this&lt;/a&gt;. It wouldn&amp;#8217;t be a crisis if it weren&amp;#8217;t a systematic and widespread phenomenon. It is understandable if every now and then a researcher comes into a conclusion, or finds some results, attributing the results to what they think is the cause of what they&amp;#8217;ve observed, and be wrong. But these kinds of &lt;em&gt;mistakes&lt;/em&gt; are not why we see an abondant irreproducible set of&amp;nbsp;publications. &lt;/p&gt;
&lt;h3 id="why-how"&gt;Why? How?&lt;a class="headerlink" href="#why-how" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&amp;#8217;s start with a simple example. Let say we want to study the influence of substance X (maybe a potential drug) on mice having disease Y. We take a group of mice, we make sure they have the disease, and then we give that substance to half of them, and see what happens. Now imagine we repeat the same &lt;em&gt;study&lt;/em&gt; 10 times, and in 3 out of 10 times we repeat the same procedure, mice show some improvement in their condition when they are given substance X, and the other 7 times, we see no improvement, or even worse, we observe they die sooner compared to the mice given nothing other than their normal food. Now, having all the information, you might say okay, it seams the substance isn&amp;#8217;t really working. But if we only take the 3 replications of the same study in which we saw an improvement in the mice, then your information would be: &amp;#8220;we tried substance X for disease Y in several mice, and repeated the study 3 times, and in all those studies substance X helped mice dealing with disease Y&amp;#8221;. Now you see a study which even has replicated the experiment 3 times, and in all of them substance X seems to be working. If someone in another lab sees this article, would think it works, and may try to replicate it. But we know there&amp;#8217;s 70% chance they won&amp;#8217;t see any improvement using X. This is an example of a study which cannot be reproduced with the claimed&amp;nbsp;results.&lt;/p&gt;
&lt;p&gt;For the next example we need a bit of&amp;nbsp;background. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We, humans, have over 20,000 genes in our &lt;span class="caps"&gt;DNA&lt;/span&gt;, and we have the technology to take a sample from a part of our body, i.e. to biopsy, and measure the activity levels of all those individual genes in the given sample, hence having over 20K measurements for each given biopsy, usually referred to as gene expression&amp;nbsp;data.&lt;/li&gt;
&lt;li&gt;Genetic abnormalities are observed in&amp;nbsp;cancer.&lt;/li&gt;
&lt;li&gt;Cancer types and subtypes vary in those abnormalities, i.e. there is difference in different cancer types in terms of their genetic&amp;nbsp;background.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to study the genetic background of cancer, biopsies are taken from cancer patients, and their gene expressions are measured. But the data coming from this process is not&amp;nbsp;perfect:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Inter-cellular processes are stochastic, meaning they don&amp;#8217;t follow a deterministic pattern. You might take two biopsies from a tissue of a healthy person, and for many reasons observe different expression levels between the&amp;nbsp;two. &lt;/li&gt;
&lt;li&gt;The process measuring the gene expression levels for many reasons adds noise to the data, which means if you repeat the process of measuring the expression levels twice from the same given biopsy, you might observe different&amp;nbsp;values. &lt;/li&gt;
&lt;li&gt;The measurement process is also prune to batch effects, which means you might observe consistently different values comparing measurements taken in two different labs across the&amp;nbsp;town.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the above reasons, plus the fact that most datasets include only a few hundred patients, i.e. rows in the data matrix, whereas we get +20K features, i.e. columns in the data matrix, for each patient, make it a hard problem to solve, and also hard to&amp;nbsp;reproduce.&lt;/p&gt;
&lt;p&gt;Now assume you want to take a published computational model, which is basically an algorithm, and apply that to some dataset you have at hand. In many cases that publication does not include enough details about how to preprocess your data. This is the part that tells you how and if you need to transform your input, keep some and ignore others, and maybe combine some of those input features together in some way. Then there is the main part, which if you&amp;#8217;re lucky, you can implement. This means if there is enough detailed explanation in the publication, you can reproduce the results given the data used in the publication, which itself is not trivial, since many publications don&amp;#8217;t publish the whole data used in their&amp;nbsp;analysis.&lt;/p&gt;
&lt;p&gt;There have been efforts by the community and journals to encourage and maybe enforce reproducibility (&lt;a href="http://www.nature.com/news/reproducibility-1.17552"&gt;example&lt;/a&gt;). For instance, some journals require you to have the code available upon request. But in practice, that code is mostly only available while the paper is under the peer review process and it&amp;#8217;s lost afterwards. Even then, it&amp;#8217;s not always easy to re-run that code anyway; they might be tuned to the hardware infrastructure available to the researcher, and in some cases even links to some data files which were available on the researcher&amp;#8217;s computer and not&amp;nbsp;released.&lt;/p&gt;
&lt;p&gt;Now let say, the publication uses only open datasets which you can easily download. And the code is available on some open repository, in such a way that you can reproduce the results of the publication on those datasets. For the reasons explained above, such as noise and batch effects, you might try the same algorithm on a different dataset of the same kind, i.e. same measurement tools and same cancer types, but achieve very different results than the one reported in the publication. In some other cases, the publication includes some claims and analysis across different cancer types, and applies the method on let say, 3 datasets of different cancer types. You might try the same method on 3 other datasets of other cancer types, and observe results which are nowhere close to the ones reported and&amp;nbsp;claimed.&lt;/p&gt;
&lt;p&gt;Unfortunately the complexity and the nature of the problem is not the only factor in having irreproducible publications. Very often it is the case that journals and peer reviewers don&amp;#8217;t actually try to reproduce the results, since it takes time and the community won&amp;#8217;t value the time a researcher would spend on those tasks. In many other cases researchers try their methods on many datasets, and choose the ones that works best for them to report. These are publications that are in best case reproducible on the datasets they mention, but as a scientific method, they are not necessarily reproducible in an independent lab, or using other&amp;nbsp;datasets.&lt;/p&gt;
&lt;p&gt;__ Negative result__: Imagine you have an idea, like an algorithm, which you think might predict how well a certain drug will perform. If you try the method and it does not deliver the performance you thought it would, or it performs worse that existing methods and algorithms, then you have a negative result at&amp;nbsp;hand.&lt;/p&gt;
&lt;p&gt;Some factors that contribute to this phenomenon are (add a sarcastic tone to most of what you read in this&amp;nbsp;section):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Publishing negative results gets you nowhere in the scientific community. You won&amp;#8217;t get grants publishing them, even if you can do so. Most journals don&amp;#8217;t accept your article if it&amp;#8217;s mostly about negative results&amp;nbsp;anyway.&lt;/li&gt;
&lt;li&gt;Reproducing other people&amp;#8217;s work is not valued. You won&amp;#8217;t be a respected researcher if you spend a lot of time trying to reproduce other people&amp;#8217;s work. You are supposed to be independent and innovative, constantly producing new results and&amp;nbsp;methods.&lt;/li&gt;
&lt;li&gt;A method working half the time is not impressive enough. That&amp;#8217;s why if your method is working on 4 datasets out of 9, you might just not report the 5 it didn&amp;#8217;t work on. Or if you want to look honest, you might only report one or two, and claim your method works most of the&amp;nbsp;time.&lt;/li&gt;
&lt;li&gt;Interpreting the results in a positive way. In many cases, you might read the publication and think it&amp;#8217;s very impressive, but if you only look at the charts, numbers, and performance measures, you wouldn&amp;#8217;t think it&amp;#8217;s particularly a better method than&amp;nbsp;others.&lt;/li&gt;
&lt;li&gt;Politics in science and peer review process discourages criticizing other people&amp;#8217;s work. Once you&amp;#8217;re at the bleeding edge of science, not many people in the world are working on what you work on. This means when you submit a paper for a peer reviewed journal, chances are your article gets reviewed by those people who you know. Although they won&amp;#8217;t see the names of the authors of the article, but they can easily guess. That&amp;#8217;s why when you encounter a paper which you cannot reproduce, you don&amp;#8217;t want to openly criticize it. After all, who needs more&amp;nbsp;enemies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yeah it&amp;#8217;s really sad and gloomy, but people are working on it, and we need much more to be&amp;nbsp;done.&lt;/p&gt;</content><category term="science"/><category term="reproducibility-crisis"/></entry><entry><title>Clue-WATTx Hackathon</title><link href="https://adrin.info/clue-wattx-hackathon.html" rel="alternate"/><published>2017-04-02T00:00:00+02:00</published><updated>2017-04-02T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2017-04-02:/clue-wattx-hackathon.html</id><summary type="html">&lt;h3 id="hackathon"&gt;&lt;a href="http://cluehackathon.wattx.io/"&gt;Hackathon&lt;/a&gt;&lt;a class="headerlink" href="#hackathon" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To me, a hackathon is when a group of people gather for a day or two, working for a somewhat common goal, develop, have fun, meet new people, and to home. Unfortunately for whatever reason, most hackathons have become a competition, with a set prize, organized by some company …&lt;/p&gt;</summary><content type="html">&lt;h3 id="hackathon"&gt;&lt;a href="http://cluehackathon.wattx.io/"&gt;Hackathon&lt;/a&gt;&lt;a class="headerlink" href="#hackathon" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To me, a hackathon is when a group of people gather for a day or two, working for a somewhat common goal, develop, have fun, meet new people, and to home. Unfortunately for whatever reason, most hackathons have become a competition, with a set prize, organized by some company. The good part is that some attendees might get some money out of the hackathon, but the down side is that it usually becomes a competition and people stop collaborating. I was very happy to see that was not very the case in this hackathon, and we had mostly a really nice atmosphere for the whole weekend. It was a pleasurable experience working and chatting with Clue and WATTx people as well as the&amp;nbsp;attendees.&lt;/p&gt;
&lt;h3 id="clue"&gt;&lt;a href="https://www.helloclue.com/"&gt;Clue&lt;/a&gt;&lt;a class="headerlink" href="#clue" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Clue is for people who experience menstruation cycles, or periods, to record their cycle, and related symptoms. These symptoms include bleeding, pain, skin condition, premenstrual syndrome (&lt;span class="caps"&gt;PMS&lt;/span&gt;), among others. The app in return, gives you predictions regarding your period, ovulation, and &lt;span class="caps"&gt;PMS&lt;/span&gt;. The app looks like&amp;nbsp;this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Clue app" src="files/img/Clue-screenshot-500x253.png" title="Credit: http://tech.eu/features/2607/clue-app-profile-ida-tin/"&gt;&lt;/p&gt;
&lt;p&gt;Using the app you can easily see if there are any irregularities in your cycle, and/or see when you should be expecting phases such as ovulation, period, or &lt;span class="caps"&gt;PMS&lt;/span&gt;, and read about menstruation cycle in general if you&amp;#8217;re interested. Some symptoms can be recorded and predicted directly, such as bleeding, others are less directly observed such as ovulation. The app uses observations from other related symptoms to predict these&amp;nbsp;phases.&lt;/p&gt;
&lt;p&gt;The data that the app collects is invaluable to a better understanding of the menstruation cycle, related diseases, and even (birth control) pills. I hope the data helps our society to understand cycles better, and potentially improve half of the population&amp;#8217;s&amp;nbsp;lives.&lt;/p&gt;
&lt;h3 id="statice-by-wattx"&gt;&lt;a href="http://statice.wattx.io/"&gt;Statice by WATTx&lt;/a&gt;&lt;a class="headerlink" href="#statice-by-wattx" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Fortunately, people at Clue value users&amp;#8217; privacy a great deal. But that means they can&amp;#8217;t have a hackathon and give people real users&amp;#8217; data to work on. Here&amp;#8217;s where the Statice platform designed by the nice folks at WATTx comes in. Their platform is still taking shape and this hackathon was also a test for them to see how the platform works. But in short, they take the real data, produce some data using the real one, which resembles the real data, but users&amp;#8217; profiles from the real data are not revealed by looking at the synthesized data. Their synthesized data was what we worked on, and using that data we developed our method. Then to test the method against the real data, we would submit our method in the form of a docker container, and they would use that container to train our models on the real data, and then test it against the test set, again from the real data. And then, we would see the score of the method, or &lt;em&gt;failed&lt;/em&gt; in case there was something wrong with the code or during the&amp;nbsp;run.&lt;/p&gt;
&lt;h3 id="goal"&gt;Goal&lt;a class="headerlink" href="#goal" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The goal of the hackathon was to analyze Clue users&amp;#8217; data given users&amp;#8217; history, and predict users&amp;#8217; symptoms for their next cycle. We were supposed to predict the probability of a user tracking a symptom for each day of the next cycle. Out of total 80 symptoms for which we had data, we were to predict only 16, but we could use other symptoms&amp;#8217; history and data for the&amp;nbsp;prediction.&lt;/p&gt;
&lt;h3 id="method"&gt;Method&lt;a class="headerlink" href="#method" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The main part of the data was in the form of user interactions. Basically one row for each (user, symptom, date) tuple. We transformed the data into one row per user as our input, and a vector for each symptom as output, and then used a simple regularized linear model to predict the output, i.e. Lasso. A more detailed explanation of the method as well as the code itself are available on &lt;strong&gt;&lt;a href="https://github.com/adrinjalali/clue-hackathon"&gt;github&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="results"&gt;Results&lt;a class="headerlink" href="#results" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At the end of the two days, we all submitted our best models to test against a test dataset which was taken out from the data for this purpose, and our team managed to win the prize for the best performing&amp;nbsp;method:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Team Rabbit" src="/files/img/clue-wattx-hackathon.jpg"&gt;&lt;/p&gt;
&lt;h3 id="organizers-summary"&gt;Organizers&amp;#8217; summary&lt;a class="headerlink" href="#organizers-summary" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A nice summary of the event was written by Laure Sorba, WATTx &lt;span class="caps"&gt;UX&lt;/span&gt; strategist, available &lt;a href="https://medium.com/wattx-stories/wattx-first-hackathon-to-advance-female-health-tech-a0677876d49e"&gt;here&lt;/a&gt;. And here is the diagram showing her summary of the event, available on the same&amp;nbsp;page:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Summary" src="https://cdn-images-1.medium.com/max/800/1*j9JuxqbpcwGUdkD6P8I04Q.png" title="Credit: medium.com"&gt;&lt;/p&gt;</content><category term="machine-learning"/><category term="hackathon"/></entry><entry><title>TV-ad Attribution, Gaussian Processes</title><link href="https://adrin.info/tv-ad-attribution-gaussian-processes.html" rel="alternate"/><published>2016-10-06T00:00:00+02:00</published><updated>2016-10-06T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2016-10-06:/tv-ad-attribution-gaussian-processes.html</id><summary type="html">&lt;h3 id="problem-description"&gt;Problem description:&lt;a class="headerlink" href="#problem-description" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This work was done in &lt;a href="https://corporate.misterspex.com/en/"&gt;Mister Spex GmbH&lt;/a&gt;, and slides of a presentation I gave at &lt;a href="https://www.meetup.com/PyData-Berlin/events/235347104/"&gt;PyData meetup&lt;/a&gt; are available now &lt;a href="/files/tv-gp-pydata-presentation.pdf"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is a website, in this case an e-shop, and we have information about user sessions on the website. We also have information about &lt;span class="caps"&gt;TV&lt;/span&gt;-ads …&lt;/p&gt;</summary><content type="html">&lt;h3 id="problem-description"&gt;Problem description:&lt;a class="headerlink" href="#problem-description" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This work was done in &lt;a href="https://corporate.misterspex.com/en/"&gt;Mister Spex GmbH&lt;/a&gt;, and slides of a presentation I gave at &lt;a href="https://www.meetup.com/PyData-Berlin/events/235347104/"&gt;PyData meetup&lt;/a&gt; are available now &lt;a href="/files/tv-gp-pydata-presentation.pdf"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is a website, in this case an e-shop, and we have information about user sessions on the website. We also have information about &lt;span class="caps"&gt;TV&lt;/span&gt;-ads shown to the public requested by the company. The question is, which of those sessions on the website are there because of the &lt;span class="caps"&gt;TV&lt;/span&gt;-ads.&lt;/p&gt;
&lt;p&gt;There are some obstacles to answer the above&amp;nbsp;question:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Users don&amp;#8217;t tell the website why they came to the website, or how they found about the&amp;nbsp;service.&lt;/li&gt;
&lt;li&gt;Users use different channels to get to the website. They might have seen an ad on &lt;span class="caps"&gt;TV&lt;/span&gt; and then have used google to find the exact address to the&amp;nbsp;website.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a result, we change the question to the following: what is the likelihood of each session to be because of a &lt;span class="caps"&gt;TV&lt;/span&gt;-ad shown recently. Hence, the above input/output is&amp;nbsp;given/desired:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Input:&lt;ul&gt;
&lt;li&gt;One entry for each session which are date-time&amp;nbsp;labeled.&lt;/li&gt;
&lt;li&gt;A list of date-time labeled&amp;nbsp;events.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Output:&lt;ul&gt;
&lt;li&gt;What is the likelihood of each session to be influenced by a nearby&amp;nbsp;event.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="prepare-the-data"&gt;Prepare the data&lt;a class="headerlink" href="#prepare-the-data" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We reduce the granularity of the data and aggregate it by minute. As a result, we have session count per minute, and the time of (&lt;span class="caps"&gt;TV&lt;/span&gt;-ad) events by minute. This results in a time series data having some points on it labeled by our&amp;nbsp;events.&lt;/p&gt;
&lt;p&gt;One way to see if the events have had an influence on our traffic, is to forget about those events, detect anomalies on our time series data, and see if they&amp;#8217;ve happened around those events. I&amp;#8217;ve used some of those methods in other projects, and they don&amp;#8217;t make me happy on this data. They either detect wrong signals as anomalies, or miss some not so obvious&amp;nbsp;signals.&lt;/p&gt;
&lt;p&gt;Before going further, let&amp;#8217;s look at the data. Fig. 1 illustrates a week worth of data. The &lt;em&gt;X&lt;/em&gt; axis represents time (1 for each minute), and the &lt;em&gt;Y&lt;/em&gt; axis shows the normalized session count. The data is normalized as &lt;em&gt;X / median(X)&lt;/em&gt; simply to anonymize the actual session counts, since the actual numbers are irrelevant to this&amp;nbsp;article.&lt;/p&gt;
&lt;p&gt;&lt;img alt="A week" src="/files/img/20161006-week.png" title="A week"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fig. 1: Normalized session count for a&amp;nbsp;week&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Some of those sharp peaks are right after a &lt;span class="caps"&gt;TV&lt;/span&gt;-ad event. Field knowledge says most of the traffic caused by a &lt;span class="caps"&gt;TV&lt;/span&gt;-ad comes up to 8 minutes after the event. I take precaution, and assume some error in reported time of the event. Now let&amp;#8217;s remove any reported session from 2 minutes before the event, to 20 minutes after the event. Fig. 2 and 3 show one day of the data, before and after removing data around reported&amp;nbsp;events.&lt;/p&gt;
&lt;p&gt;&lt;img alt="A week" src="/files/img/20161006-day.png" title="A day"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fig. 2: Normalized session count for a&amp;nbsp;day&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="A week" src="/files/img/20161006-day-afterremoval.png" title="A week"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fig. 3: Normalized session count for a day, after removing data around reported&amp;nbsp;events&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="method"&gt;Method&lt;a class="headerlink" href="#method" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Intuitively speaking, I would like to remove the parts of the data close to the given events, fit a model to the remaining data, and then see how close the observed data is to the model&amp;#8217;s predictions. If the observed values are significantly higher than the predicted values, most probably some of those sessions are because of the&amp;nbsp;event.&lt;/p&gt;
&lt;p&gt;Given an observed and predicted values, deciding whether or not the observed value is &lt;em&gt;significantly&lt;/em&gt; larger, can be tricky, and in some cases very arbitrary. Using a method which gives you the probability of an observed value at a given input would make the process much easier. One way of achieving such a goal is to have a method which, intuitively speaking, tells you what it thinks the predicted value is, and also how confident it is. A Gaussian Process (&lt;span class="caps"&gt;GP&lt;/span&gt;) is such a model, in a way that it gives a normal distribution at a given input point as the output. This predicted output has a mean and a variance, which we use to see how probable a given observation is, under the assumption that the model correctly describes the&amp;nbsp;data.&lt;/p&gt;
&lt;p&gt;Given a predicted normal distribution, the further the observed value is from the expected mean, the less expected it is. In other words, the larger the blue area shown in Fig. 4, the more probable it&amp;#8217;s an&amp;nbsp;outlier.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Normal Distribution" src="/files/img/20161006-normal.png" width="40%"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fig. 4: Normal distribution and three different observed values - credit:&amp;nbsp;thefemalecelebrity.com&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The area under the curve marked by the blue areas shown in Fig. 4 is between 0 and 1. It is 0 if the expected value is the same as our observed value, and is close to 1 if it is the two observed and expected mean are far from each other. Hereafter &lt;em&gt;score(x)&lt;/em&gt; represents this area under the curve. The piece of code bellow shows how this is calculated in&amp;nbsp;python:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;math&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;scipy&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;phi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;scipy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;special&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;phi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;x_score&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expected_mean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expected_std&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now for a moment, assume we know a given data point (number of sessions) is influenced by a &lt;span class="caps"&gt;TV&lt;/span&gt;-ad. Still not all those sessions are because of the event. Some of them would have been there even with no &lt;span class="caps"&gt;TV&lt;/span&gt;-ad event. We take the predicted mean as the background session count, and the rest as &lt;span class="caps"&gt;TV&lt;/span&gt;-ad influenced sessions. Therefore, if &lt;em&gt;x&lt;/em&gt; is observed value, and &lt;em&gt;x&amp;#8217;&lt;/em&gt; is predicted value, &lt;em&gt;(x - x&amp;#8217;) / x&lt;/em&gt; is the portion of sessions attributed to a &lt;span class="caps"&gt;TV&lt;/span&gt;-ad&amp;nbsp;event.&lt;/p&gt;
&lt;p&gt;At the end, we take &lt;em&gt;score(x) * (x - x&amp;#8217;) / x&lt;/em&gt; as the likelihood of each session being attributed to a &lt;span class="caps"&gt;TV&lt;/span&gt;-ad.&lt;/p&gt;
&lt;h3 id="implementation-and-results"&gt;Implementation and Results&lt;a class="headerlink" href="#implementation-and-results" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I used &lt;em&gt;Python3&lt;/em&gt;, &lt;em&gt;matplotlib&lt;/em&gt; to generate the plots, and &lt;em&gt;GPy&lt;/em&gt; to train the Gaussian Process&amp;nbsp;model.&lt;/p&gt;
&lt;p&gt;There are at least two ways of fitting and using GPs in our setting. One is to train a really nice model using the historical data, and use the saved trained model to get predictions for future data.
By looking at the data, I would sum these three kernels and optimize on the&amp;nbsp;data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A periodic kernel to handle&amp;nbsp;periodicity&lt;/li&gt;
&lt;li&gt;A Gaussian (&lt;span class="caps"&gt;RBF&lt;/span&gt;) kernel to handle the non-periodic part of the&amp;nbsp;data&lt;/li&gt;
&lt;li&gt;A white noise kernel to handle fluctuations seen in the&amp;nbsp;data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because there were no big enough server available, training a model on the historical data at once was not feasible. Instead, for each day, I take a small part of the data which includes 10 hours before and after start and end of the day, and train a model on that part of the data. This makes training of the model on a small machine feasible, and it also doesn&amp;#8217;t require the periodic kernel, which makes the optimization process even faster. Therefore I only use these two&amp;nbsp;kernels:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Gaussian (&lt;span class="caps"&gt;RBF&lt;/span&gt;) kernel to handle the non-periodic part of the&amp;nbsp;data&lt;/li&gt;
&lt;li&gt;A white noise kernel to handle fluctuations seen in the&amp;nbsp;data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To summarize, here&amp;#8217;s what I&amp;nbsp;do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For a given date, take the 44 hours of data corresponding to the given date (10 hours before and 10 hours after the beginning and the end of the day&amp;nbsp;respectively)&lt;/li&gt;
&lt;li&gt;Remove the part of the data around given any &lt;span class="caps"&gt;TV&lt;/span&gt;-ad events in that&amp;nbsp;range.&lt;/li&gt;
&lt;li&gt;Fit a &lt;span class="caps"&gt;GP&lt;/span&gt; to the&amp;nbsp;data.&lt;/li&gt;
&lt;li&gt;Calculate the abovementioned scores for each data point which corresponds to one&amp;nbsp;minute.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using &lt;em&gt;GPy&lt;/em&gt;, I train the model&amp;nbsp;as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;kernel = GPy.kern.RBF(input_dim=1) + GPy.kern.White(input_dim=1)
m = GPy.models.GPRegression(Xtr.reshape(-1,1),ytr.reshape(-1,1),kernel)
m.optimize()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above&amp;nbsp;code, &lt;code&gt;Xtr&lt;/code&gt; and &lt;code&gt;ytr&lt;/code&gt; are the input/output vectors respectively.&amp;nbsp;The &lt;code&gt;Xtr&lt;/code&gt; is a sequence of integers representing the minute distance from where the data started,&amp;nbsp;and &lt;code&gt;ytr&lt;/code&gt; is the normalized number of sessions for that minute. This results in a model depicted in Fig. 5. The blue gradient represents the variance of the expected output, showing the expected value should be somewhere in the blue region. Please note that we&amp;#8217;re only interested in the regions inside the data, and not the region outside the data&amp;nbsp;range.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Trained GP" src="/files/img/20161006-GP.png" title="Trained Gaussian Process Model"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fig. 5: The trained Gaussian Process model on the 44h of&amp;nbsp;data.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Table 1 shows calculated scores and likelihoods of each session in each minute to be influenced by a &lt;span class="caps"&gt;TV&lt;/span&gt;-ad. A negative portion and likelihood simply mean the expected value is larger that the observed, and can safely be ignored. The &lt;em&gt;Is Significant&lt;/em&gt; column simply flags if the score is over &lt;em&gt;0.9&lt;/em&gt;. I would personally attribute only sessions of those minutes to a &lt;span class="caps"&gt;TV&lt;/span&gt;-ad. Also, as expected, not all &lt;span class="caps"&gt;TV&lt;/span&gt;-ad events result in significant rise in the traffic, and some clearly result in more traffic than&amp;nbsp;others.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: right;"&gt;Observed&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Expected Mean&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Expected Variance&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Score&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Portion&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Likelihood&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Is Significant&lt;/th&gt;
&lt;th style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;-ad&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.52&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.52&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.83&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.01&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.51&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.81&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.68&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.67&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.24&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.16&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.01&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.72&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.52&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.09&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.70&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.60&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.20&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.12&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.65&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.10&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.89&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.55&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.55&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.29&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.28&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.94&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.41&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.04&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.01&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.49&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.83&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.08&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.48&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.23&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.98&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.31&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.31&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.20&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.01&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.74&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.18&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.14&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.77&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.38&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.04&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.73&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.18&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.13&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.20&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.89&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.24&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.82&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.17&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.95&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.28&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.27&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.59&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.08&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.79&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.32&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.03&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.84&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.22&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.64&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.80&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.35&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.28&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.01&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.41&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.04&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.07&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.83&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.34&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.99&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.35&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.35&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.85&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.25&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.83&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.88&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.77&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.88&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.48&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.07&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.88&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.59&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.08&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.62&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.88&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.46&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.46&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.47&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.88&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.40&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.26&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.89&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.97&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.29&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.29&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.89&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.92&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.26&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.28&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.89&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.97&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.30&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.89&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.89&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.82&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.17&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.15&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.90&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.22&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;4.45&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.90&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.80&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.80&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;5.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.90&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.83&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.83&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;3.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.90&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.72&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.72&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;2.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.61&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.61&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.54&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.54&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.98&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.54&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.54&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.97&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.29&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.47&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.92&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.38&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.37&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.94&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.92&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.08&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.92&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.35&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.08&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.93&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.99&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.34&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.34&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.93&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.97&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.28&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.28&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.93&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.70&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.11&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.93&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.07&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.94&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.18&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.53&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.94&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.39&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.39&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.94&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.18&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.95&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.81&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.95&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.81&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.15&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.95&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.64&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.09&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.55&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.38&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.38&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;2.43&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.60&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.60&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.51&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.36&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.36&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.62&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.97&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.40&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.26&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.97&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.97&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.97&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.32&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.98&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.80&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.18&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.14&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.98&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.55&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.89&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.98&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.42&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.04&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.99&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.94&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.24&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.22&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.99&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.59&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.07&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.99&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.77&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.13&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.28&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.22&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.20&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.20&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.53&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.34&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.34&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.26&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.01&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.20&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.17&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.01&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.44&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.04&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.34&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.01&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.24&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.26&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.86&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.00&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.76&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.63&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.08&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.81&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.83&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.27&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.23&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.25&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.23&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.78&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.13&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.36&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.24&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.71&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.20&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.14&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.24&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.36&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.95&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.23&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.22&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.05&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.15&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.32&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.26&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.72&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.10&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.22&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;2.57&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.58&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.58&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;2.77&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.60&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.60&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.51&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.99&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.27&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.27&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.80&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.15&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.34&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.18&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.16&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.79&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.15&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.01&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.30&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.78&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.15&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.11&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.07&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.03&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.23&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.56&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.10&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.38&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.94&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.20&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.55&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.07&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.32&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.80&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.15&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.40&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.62&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.12&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.31&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.30&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.36&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.87&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.15&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.32&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.02&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.96&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.73&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.18&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.13&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.72&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.34&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.34&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.34&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.02&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.28&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.64&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.07&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.04&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.13&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.45&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.04&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.28&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.63&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.11&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.07&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.34&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.81&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.15&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.12&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.26&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.55&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.05&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.21&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.36&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.06&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.26&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.54&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.09&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.05&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.40&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.91&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.19&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.17&lt;/td&gt;
&lt;td style="text-align: center;"&gt;*&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;1.00&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.64&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.09&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right;"&gt;0.98&lt;/td&gt;
&lt;td style="text-align: right;"&gt;1.14&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.02&lt;/td&gt;
&lt;td style="text-align: right;"&gt;0.71&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.17&lt;/td&gt;
&lt;td style="text-align: right;"&gt;-0.12&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Table 1: A piece of output of the&amp;nbsp;method&lt;/em&gt;&lt;/p&gt;</content><category term="machine-learning"/><category term="gaussian-processes"/><category term="attribution"/></entry><entry><title>On the ethics of CRISPR</title><link href="https://adrin.info/on-the-ethics-of-crispr.html" rel="alternate"/><published>2015-09-01T00:00:00+02:00</published><updated>2015-09-01T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2015-09-01:/on-the-ethics-of-crispr.html</id><summary type="html">&lt;p&gt;&lt;img alt="Taken from http://www.economist.com/news/leaders/21661651-new-technique-manipulating-genes-holds-great-promisebut-rules-are-needed-govern-its" src="/files/img/economist-editing-humanity.jpg" title="Credits: Economist"&gt;&lt;/p&gt;
&lt;p&gt;I was reading &lt;a href="http://www.economist.com/news/leaders/21661651-new-technique-manipulating-genes-holds-great-promisebut-rules-are-needed-govern-its"&gt;this article&lt;/a&gt; on the ethics of editing human genome and I realized there&amp;#8217;s a missing point in&amp;nbsp;there.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/CRISPR"&gt;&lt;span class="caps"&gt;CRISPR&lt;/span&gt;&lt;/a&gt; in short is a technology that allows us to edit our own genome. Of course it has countless number of useful applications as it&amp;#8217;s very simply …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Taken from http://www.economist.com/news/leaders/21661651-new-technique-manipulating-genes-holds-great-promisebut-rules-are-needed-govern-its" src="/files/img/economist-editing-humanity.jpg" title="Credits: Economist"&gt;&lt;/p&gt;
&lt;p&gt;I was reading &lt;a href="http://www.economist.com/news/leaders/21661651-new-technique-manipulating-genes-holds-great-promisebut-rules-are-needed-govern-its"&gt;this article&lt;/a&gt; on the ethics of editing human genome and I realized there&amp;#8217;s a missing point in&amp;nbsp;there.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/CRISPR"&gt;&lt;span class="caps"&gt;CRISPR&lt;/span&gt;&lt;/a&gt; in short is a technology that allows us to edit our own genome. Of course it has countless number of useful applications as it&amp;#8217;s very simply depicted in the above picture (credit: economist). But recently Chinese scientists have genetically modified human embryos (&lt;a href="http://www.nature.com/news/chinese-scientists-genetically-modify-human-embryos-1.17378"&gt;link&lt;/a&gt;). Fortunately there&amp;#8217;s been some discussion going on in the community about the ethics of editing human embryo&amp;#8217;s genome, or in general human&amp;nbsp;genome.&lt;/p&gt;
&lt;p&gt;The question I want people to think about is: who should/will have access to this technology? Obviously this technology will be very expensive when it reaches the market. Does it mean only rich people will be able to use it? And I&amp;#8217;m not talking about the applications which concern diseases; I&amp;#8217;m rather talking about editing your child&amp;#8217;s genome, to make it smarter, or stronger, or whatever you feel like&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;We already have too much of a difference between classes in our society. This difference has been empowered partially, if not mostly, by the fact that people have been able to accumulate wealth through time and even generations. If we allow them to be the ones benefiting a technology like &lt;span class="caps"&gt;CRISPR&lt;/span&gt;, we will practically give them the power to annihilate the lower classes through&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;One piece of good news is that some people are talking about how to regulate this sort of technology (&lt;a href="http://www.nature.com/news/regulate-gene-editing-in-wild-animals-1.17523"&gt;link&lt;/a&gt;). I believe we should start a conversation about who should have access to the technology. This concern is regardless of how and what we decide about the ethics of the method for different applications. If we, as human species, decide not to use it at all, then nobody has access to it. But if we give it a go, then we should make sure all classes of the society have equal access to it. The least and the last we need is to have a rich sub-population with higher physical and mental&amp;nbsp;capabilities.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;EDIT&lt;/span&gt;&lt;/strong&gt;: Thanks to Ian Sample, found a podcast by the guardian &lt;a href="http://www.theguardian.com/science/audio/2015/may/01/genetics"&gt;here&lt;/a&gt;.&lt;/p&gt;</content><category term="ethics"/><category term="ethics"/><category term="genome"/></entry><entry><title>Zimbra Auto Provisioning from FreeIPA</title><link href="https://adrin.info/zimbra-auto-provisioning-from-freeipa.html" rel="alternate"/><published>2015-08-07T00:00:00+02:00</published><updated>2015-08-07T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2015-08-07:/zimbra-auto-provisioning-from-freeipa.html</id><summary type="html">&lt;p&gt;After quite a few days struggling to configure a Zimbra server so that it automatically fetches users from our freeIPA (&lt;span class="caps"&gt;LDAP&lt;/span&gt;) server, I finally managed to have a configuration which works. I got help from a bunch of pages like &lt;a href="http://imanudin.net/2014/12/09/zimbra-external-ad-automatically-create-mailboxes-zimbra-with-lazy-mode-auto-provisioning/"&gt;this&lt;/a&gt; and &lt;a href="https://www.zimbra.com/docs/ne/8.0.2/administration_guide/wwhelp/wwhimpl/js/html/wwhelp.htm#href=ZCS_8_0_2_Admin_Guide.Auto_Provisioning_New_Accounts_from_External_LDAP.html"&gt;this&lt;/a&gt; one. This comes after you fix the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;After quite a few days struggling to configure a Zimbra server so that it automatically fetches users from our freeIPA (&lt;span class="caps"&gt;LDAP&lt;/span&gt;) server, I finally managed to have a configuration which works. I got help from a bunch of pages like &lt;a href="http://imanudin.net/2014/12/09/zimbra-external-ad-automatically-create-mailboxes-zimbra-with-lazy-mode-auto-provisioning/"&gt;this&lt;/a&gt; and &lt;a href="https://www.zimbra.com/docs/ne/8.0.2/administration_guide/wwhelp/wwhimpl/js/html/wwhelp.htm#href=ZCS_8_0_2_Admin_Guide.Auto_Provisioning_New_Accounts_from_External_LDAP.html"&gt;this&lt;/a&gt; one. This comes after you fix the external &lt;span class="caps"&gt;LDAP&lt;/span&gt; authentication and probably also external &lt;span class="caps"&gt;GAL&lt;/span&gt; configuration on your Zimbra&amp;nbsp;server.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zmprov&lt;/code&gt; gives you a nice terminal to configure the&amp;nbsp;server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;su&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;zimbra
$&lt;span class="w"&gt; &lt;/span&gt;zmprov
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the set of commands I used to set it&amp;nbsp;up:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;prov&amp;gt; md mysampledomain.net zimbraAutoProvAccountNameMap &amp;quot;uid&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvAttrMap &amp;quot;givenName=givenName&amp;quot;
prov&amp;gt; md mysampledomain.net +zimbraAutoProvAttrMap &amp;quot;sn=sn&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvBatchSize 80
prov&amp;gt; md mysampledomain.net zimbraAutoProvLdapAdminBindDn &amp;quot;uid=mail_server,cn=users,cn=accounts,dc=mysampledomain,dc=net&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvLdapAdminBindPassword &amp;quot;myverysecretpassword&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvLdapBindDn &amp;quot;uid=mail_server,cn=users,cn=accounts,dc=mysampledomain,dc=net&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvLdapSearchBase &amp;quot;cn=accounts,dc=mysampledomain,dc=net&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvLdapSearchFilter &amp;quot;(&amp;amp;(ObjectClass=person))&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvLdapStartTlsEnabled TRUE
prov&amp;gt; md mysampledomain.net zimbraAutoProvLdapURL &amp;quot;ldaps://ipa.mysampledomain.net:636&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvPollingInterval &amp;quot;10m&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvScheduledDomains &amp;quot;mysampledomain.net&amp;quot;
prov&amp;gt; md mysampledomain.net zimbraAutoProvMode &amp;quot;EAGER&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To diagnose why the system wasn&amp;#8217;t working, I also had to figure out where the log files are, and how to produce more logs. Oddly enough, they&amp;#8217;re not&amp;nbsp;in &lt;code&gt;/var/log&lt;/code&gt;, and instead they are written by default&amp;nbsp;in &lt;code&gt;/opt/zimbra/log/mailbox.log&lt;/code&gt;, or other related files in that folder. I&amp;nbsp;added &lt;code&gt;log4j.logger.zimbra.autoprov=TRACE&lt;/code&gt; at the end of&amp;nbsp;my &lt;code&gt;/opt/zimbra/conf/log4j.properties&lt;/code&gt; file, which will be overwritten next time I restart the services using the configurations&amp;nbsp;in &lt;code&gt;/opt/zimbra/conf/log4j.properties.in&lt;/code&gt;. Finally to make the logging system reload the logging configuration, you need to&amp;nbsp;run &lt;code&gt;zmprov rlog&lt;/code&gt;. You find more info &lt;a href="http://wiki.zimbra.com/wiki/Using_log4j_to_Configure_mailboxd_Logging"&gt;here&lt;/a&gt;.&lt;/p&gt;</content><category term="sysadmin"/><category term="zimbra"/><category term="freeipa"/><category term="ldap"/></entry><entry><title>synapse.org</title><link href="https://adrin.info/synapseorg.html" rel="alternate"/><published>2014-06-10T00:00:00+02:00</published><updated>2014-06-10T00:00:00+02:00</updated><author><name>adrin</name></author><id>tag:adrin.info,2014-06-10:/synapseorg.html</id><summary type="html">&lt;p&gt;I decided to actually write on this blog (decision was made this morning and is final :D&amp;nbsp;).&lt;/p&gt;
&lt;p&gt;On June 2nd I received an email from my adviser telling me about the &lt;a href="https://www.synapse.org/Portal.html#!Challenges:DREAM"&gt;&lt;span class="caps"&gt;DREAM&lt;/span&gt; Challenges&lt;/a&gt;. I kind of liked it as some sub-challenges fit exactly what I&amp;#8217;ve been doing for that …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I decided to actually write on this blog (decision was made this morning and is final :D&amp;nbsp;).&lt;/p&gt;
&lt;p&gt;On June 2nd I received an email from my adviser telling me about the &lt;a href="https://www.synapse.org/Portal.html#!Challenges:DREAM"&gt;&lt;span class="caps"&gt;DREAM&lt;/span&gt; Challenges&lt;/a&gt;. I kind of liked it as some sub-challenges fit exactly what I&amp;#8217;ve been doing for that past few months, and that project is already in a phase that we&amp;#8217;ve submitted a manuscript about it. So why&amp;nbsp;not?&lt;/p&gt;
&lt;p&gt;Going through their pages, I realized they&amp;#8217;ve got a python client to interact with their databases; that&amp;#8217;s cool, but it didn&amp;#8217;t support python 3. As a result I made &lt;a href="https://github.com/Sage-Bionetworks/synapsePythonClient/pull/150"&gt;this pull request&lt;/a&gt; and at the moment of writing this post, they seem to be interested in accepting the commits (although the changes are not perfect and/or complete and more work is&amp;nbsp;required).&lt;/p&gt;
&lt;p&gt;Later I was reading challenge descriptions which made me interact with the website for a while, and that made me a bit frustrated. I have to say, I&amp;#8217;m not a web-developer and I&amp;#8217;m talking as a simple end&amp;nbsp;user.&lt;/p&gt;
&lt;p&gt;If I was the web-site&amp;#8217;s development manager, I&amp;#8217;d add these to the first possible &lt;a href="http://www.scrumalliance.org/community/articles/2007/march/glossary-of-scrum-terms#1118"&gt;sprint&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add a proper navigation system to the website; currently you can only easily navigate within a challenge/project. You need to go to the home page first to go anywhere&amp;nbsp;else.&lt;/li&gt;
&lt;li&gt;Try to go to &lt;span class="caps"&gt;DREAM&lt;/span&gt; challenges, you need to go to the home page, wait for that timer based frame to come which has the link to the challenge, click on it. In my browser (chromium), I have to refresh the whole page if I miss it once, or wait for it to come again. So: add proper links, menus, or whatever you think suits the framework for a nice navigation to&amp;nbsp;projects.&lt;/li&gt;
&lt;li&gt;Within a challenge description page, click on a link and the whole page will be reloaded, slowly and painfully. For some reason the layout of the page changes through time after each part of the page is loaded. A simple markdown based static website works much faster and better, if you want it to be fancy, add proper &lt;span class="caps"&gt;AJAX&lt;/span&gt; components/codes to make it smooth and fast. The website has serious performance issues and seems unnecessarily&amp;nbsp;heavy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;m pretty sure developers have their reason for having the website the way it is, but those reasons must be&amp;nbsp;justified/changed.&lt;/p&gt;</content><category term="blog"/><category term="dream-challenge"/></entry></feed>