This blog is a narration of 3 pivotal decisions I’ve made in my formative years that shaped my core.
To get your attention, here’s a list of companies/programs that I’ve interned at in during my university time (all off-campus):
I’ll take you through a journey starting with having nothing to add on my resume, to deleting experiences so that I can fit everything on a single page.
I did my schooling from Delhi.. which at the time used to have a state-quota of 80% seats.
So with my decent-ish rank, I had options to choose from some premier instituitions: Delhi Technological University (DTU), Netaji Subhas University of Technology (NSUT), Indraprastha Institute of Information Technology (IIIT-Delhi), among other colleges through JAC (Joint Admission Committee), Delhi.
I however did something else entirely, which did not pass muster with a lot of people.
By and through the counselling time, I had realised something important about myself. Up till this point, the only awareness I had was on my academic (and a few off-beat) pursuits, which left my personal skills largely uncharted.
Sure, I’d participated in a few school events.. but it wasn’t nearly enough “co-curricular”..
Akin to fleeting touch of water on your fingertips.. instead of an immersive plunge I feel it really should have been?
In this wave of self-awareness, figuring out the gaping holes in my “wisdom”.. a chain of thoughts led me to the first pivotal decision to shape my core:
I decided to move away from Delhi, and my comfort zone with it.
I might’ve been inspired from Siddhartha Gautama’s story.. now that I look back at it. But as long as I was in my comfort zone I would’ve never understood what I never knew.
And that is why I went ahead with All India (JoSAA) counselling, instead of Delhi’s JAC board.. and eventually ended up at Indian Institute of Information Technology, Gwalior.
As I stepped on this new path of self-discovery, my immediate focus shifted toward honing my communication skills - both verbal and written - developing the confidence to express myself openly.
So I actively engaged in a lot of events, clubs and extracurricular activities.
A few months later, I acted out Mark Antony’s “Friends, Romans, Countrymen” speech (embedded it in my memories from school) on a stage, entitling me to Mr. Parichay (Or Mr. Fresher, as some dialects dictate).
^This was the beginning of two semesters full of participating/organising/part-timing as a pet owner (long story).
All this virtually left no time for any technical development.. or so I thought.
Sure, me and some of my friends occassionally used to solve one or two coding problems ~ slowly building up an ego blanket of being 5 star coders on Hackerrank 😜, then blaming the myriad of to-be-learnt topics when we couldn’t solve two oots of problems in a competitive setting.
I used to look at other masters of coding in my batch and feel the impostor syndrome kicking in (I had CS in +2) ~ but then waves of procrastination used to take away my zeal, and I’d anyways always have something to fill my time up with.
All this built up profound unawareness came crashing, as I ended my first year with no solid technical improvements ~ this was time for the second pivotal decision that shaped my core.
Determined to reach a technological epiphany, I decided to completely remove Windows from my potato PC, and embraced Linux as my one and only.
Now this might not sound like a “pivotal” decision to the reader.. but as I reflect on it while penning down this blog, I can’t help but break into a Cheshire cat’s grin.. having confidence that this small decision had a huge impact on my core. How?
It taught me how to struggle my way through problems, especially when there’s no one around to help you.
I kid you not, there had been countless nights of me stomping my head on my own laptop to get the bluetooth module working, for example. 😂
My roommate from first year had this newfangled interest in Machine Learning by the end-semester summer holidays, at the time:
I had ample amount of time by this point, as I decided to remove myself from some organisations / clubs / activities.
Except the dramatics and a techno-managerial forum (both endowed me the best mentors I’ve had) 💫
So I really took my friend’s advice when he said:
“Deep Learning ke courses karle, usme Machine Learning bhi seekh jayega.”
(Do Deep Learning courses, they’ll teach you Machine Learning as well)
This was downright one of the worst advices I’ve ever been given that I’d religiously followed.
(If you do not count Engineering in itself 😉 ~ jk)
So I started these deep learning courses, which showed me all these gorgeous graphics for linear regression 🥰… but then started with Reinforcement learning/Generative models 💀??!
Obviously, things started shoo’ing over.. I realised I needed some mathematical foundations before all this.. so I started all over in my 3rd semester with Andrew Ng’s courses, and learning Python from the very basics.
Before I move ahead with the story, I’d like to quickly mention the time I did an unpaid internship at DRDO (Defence Research and Development Organisation) during the summer vacations at the end of my 1st year in Delhi.
So I empathise with juniors who come up to me ask should they consider doing an unpaid internship too: “..but in these times? hell naw kid”.
Jumping back to a year later.. by the end of my 2nd year I got an opportunity to work with a team in Boston around their virtual physical rehabilitation application using Machine Learning.
Specifically, Human Pose Estimation. (read about HPE, interesting concept)
This was my first internship with a stipend ~ was paid in some peanuts.
Most of my work involved around fixing/improving a subpar C++ codebase that handled the heavy lifting (inferencing through a human-pose-estimation model), intended to run on both iOS and Android.
One eventuality from this internship was that it made me weigh up so many research papers, it ignited my research interest, too. (only to be crushed later ~ read further)
I shared this cool application of HPE with a friend (also interested in data side of ML).. and without skipping a beat we dove into experimenting & writing our own research paper. Surprisingly, it got accepted at a conference and is now up on the ACM digital library:
With me choosing to end that machine learning internship (and the full-time role they were willing to offer alongside college), I went through another round of self-awareness epiphany.. which led me to the third pivotal decision to shape my core.
On a deeper self-retrospective, I cognized that during my “machine learning” internship I was more excited about the practical improvements (fixing haywire of pointers/memory leaks/logical flaws) I made to the source code.. than the research/theoretical part of it.
Moreover, from an applied engineering perspective, trying to find a job in this landscape without a decent research background or interest was (and is) tough.
Given this line of reasoning, I decided to put an end to my short stint of machine learning jouney and switch to a traditional software engineering path.
What do I mean by a “software engineering” path? I started low-level code-contributions to open-source libraries I usually used at that time:
..which later helped me during my Google Summer of Code, but we’ll get to that in a bit.
A lot of times people demand genuity in projects, and usually scorn at template projects (that’s right, looking at you, TO-DO List in React). While template projects have their merits, they tend to simply pale in comparison to the fiercely competitive landscape.
Most of my batchmates/seniors/juniors used to follow the trend of learning MERN stack to dive deeper in backend/frontend paradigms. I however don’t share the same journey as them.. coming from a Python/C++ background, I decided to stick with those languages to plunge into backend.
This fellowship was in January ‘21 (6th semester), and with lockdown imposed I had exorbitant amounts of time ~ contributing to open source, figuring out the “Data Structures & Algorithms” part of my journey, etc.
I never explored DSA in depth before the end of my 3rd year.
During this MLH Fellowship, I learnt two soft skills.. how to:
Only the projects that I worked on during this fellowship exist on my resume (as of today, the time of writing this). I wrote blogs about them, ofcourse.. a habit I highly procrastinate-yet-love.
This was during the summer holidays (as if that mattered during lockdown) at the end of my 3rd year.
A generic day used to look like this:
…
My theory was simple: stay enough time on your PC, and there’s bound to be a productive time when some 10 minutes are worth 10 long hours)
This will probably hurt a lot of influencers’ opinions, but I needed data structures and memoised recursions for my work at Matplotlib during GSoC. 😆
While my GSoC project involved some low-level programming (details in my other blogs), my immediate next internship involved working with highly abstracted frameworks such as Flask/MongoDB/GraphQL with a very-early team based in San Francisco for a retreat-planning software.
GSoC community helped me here, to get in touch with them.
Since I was dealing in dollars this time, this internship is when I made max bucks with half as much pressure compared to Indian firms.
I interviewed with FamPay (applied directly, without a referral).. just as my previous internship ended.
The next few months of FinTech experience was when I really started understanding how real life applied software engineering works at noticeable scale.
Some takeaway learnings:
With the conclusion of this internship, I finally felt that feeling of self-reliance (very rare these days).. that I probably won’t go jobless when I graduate.
This was an optimistic hunch, I never knew placements for 2023 batch will be godawful.
Cut short a few months, I applied to SuprDaily (a Swiggy acquisition) for a software engineering internship position.. this time with a referral.
The entire concept of internship hunt had started becoming gruelling, now that OaaS was becoming popular.
(Section of my previous blog, for context)
Most of this internship revolved around building Proof of Concepts (PoCs) for real-time demand shaping based on Go services (my first interaction ever with this language).
Some takeaway learnings:
As my fifth and final year began, I started gaining clarity of what the upcoming months and quarters had in store for me.
When the internship at SuprDaily ended, I received a summer internship offer from Mercari JP.
The complete interview and relocation process is documented here.
And so, after a long set of walks around the academic/administration/stationary to get NOC, I travelled to Japan.. solo.
Speaking of solo, here’s a list of random spontaneous things I regularly engaged in:
A couple months after I came back to India, I interviewed with this Bangalore-based startup offering crazy benefits. (It was my last semester, so I was allowed to go on-site again)
I had some amazing ownership at BharatX as an intern, where I developed real-time fraud prevention services from the get-go.
Even though the exposure to the startup ecosystem & monetary benefits were immense, I felt “too much” ownership at this early stage of my career was like a double-edged sword.
Why?
Those few months in Bangalore made me endure some great lows and highs, enough for me to make some pivotal decisions (fully envisioning it documented if I was writing this article a few years down the line).
I left after a few months, not primarily because of these reasons, but mostly due to my personal reasons.
Headout was the icing on the cake of my college internship journey - it was just what I needed at that point.
I applied via internal referral and joined their booking-management (backend) team in April ‘23.
With absolutely brilliant engineers around me, I had an exhilarating time there. Some key takeaways this time:
After five years of a rollercoaster career journey, it was about time I jotted down some of the minute parts (mostly tech-related).. making sure not to mention countless non-academic escapades - some are probably better off reserved for me.. and some to my friends (BH-1 supremacy). 😝
I joined Mercari as a full-time employee in October ‘23.. around the same time I’m writing this tenth-rate of a blog.
With what I’ve seen and experienced, here’s some generic software-engineering things I feel might be relevant:
This is one of the most important learnings a lot of people miss out on.. there’s no “enough-time” to master things in software engineering.
It’s like a scoop of honey which you can’t just lick once (and immediately know-it-all).. it gets thicker and sweeter as you spend time stirring it.
^This is how I now define “backend” to people.. might be true for a whole lot of other concepts, too.
Looking back to whatever short amount of time I can look back at, I’d credit a lot to the amazing mentors I’ve had along the way. 🙇🏻
I was helped out with:
Here’s a piece of advice if you’re someone in your formative years:
While a good mentor can undoubtedly propel you far on journey, don’t forget that your own efforts and groundwork play an equally crucial role in shaping you.
I have utmost respect for the concept of struggle. I strongly believe it adds value to your life regardless of the result, directly or indirectly.
You may not be very bright, you may not possess natural skills (personal attacc).. but if given enough time, your hard-smart-work will always get you either:
I hope this adds value to your life, reader.
I’m off-to new experiences ~ and I wish the same for you. ❤️
Dropping my socials in case you wanna have a chat (or have a doubt):
| Website: | aitikgupta.com - You’re here right now |
| LinkedIn: | linkedin.com/in/aitikgupta |
| GitHub: | github.com/aitikgupta |
| Instagram: | instagram.com/aitikgupta |
…you get the point, I go by @aitikgupta throughout the web! \o/
]]>You can skip to relevant sections, if that’s your thing. 🙃
I’ll plug in a sweet summary from their careers website:
Mercari Group is a Japan-based corporate group operating in both Japan and the US under a mission of “create value in a global marketplace where anyone can buy & sell.”
Mercari Group operates several businesses. The first is Mercari, Japan’s largest marketplace app allowing anyone to enjoy easily buying and selling items from their smartphone. Additionally, the Group offers Merpay, a simple, entirely in-app payment service, and Mercari Shops (Souzoh), an e-commerce platform for small businesses.
I joined the company in the summer of 2022, with a position of Software Engineer Intern (Backend) - Mercari, viz. the marketplace application.
What caught my eye (and eventually helped me in my interviews) were these standard mnemonics:
I reminisce about so many exemplars, virtually in messages/policies/docs and on-site conversations, reminding me of this. 🙌
The entire application + interview rounds + relocation took about 2.5 months, with relocation being the longest (and may I say, tedious 😂) component.
It was late February in ‘22, I heard one of my college friends scoring an off-campus internship at some company in Japan.
Now given that time’s barren lands of companies visiting on-campus for internships, it immediately caught everyone’s attention. And like everyone else (😂), I congratulated the boi 🔥 and glimpsed at the JD of the internship.
It came as a reminder of my denseness, that I had already noticed the opening in January ‘22 at one of many OaaS platforms out there, but I didn’t pay much attention to it then.
OaaS: Opportunities as a Service - as I like to call it 😝
Hitherto, the sheer hopelessness got the better of me.
The internship was in Tokyo, Japan, and some of the description was written in Japanese!
I was preemptively frustrated the company would send out template rejections because of Visa/work authorisation requirements.
I know people would sync with the extreme resentment for template rejections, but as a friendly reminder, we should always read the description thoroughly:
Well, look at that.
Relocation + Visa support 💫
At the time of applying, I believed that my internship would be in a remote setting, similar to my friend’s. Only after the interview rounds was I conveyed that I’ll be travelling to Tokyo for the internship! 💀
The friend from college (Sayantan) didn’t join yet; he couldn’t refer me, so I quickly scanned LinkedIn and sent personalised connection requests to multiple employees of Mercari.
I made a few genuine connections, some of whom I’m in occasional contact with (Rishabh), and have helped me along the way. 🤝
Applying was the only remaining step after being referred by a very friendly and supportive employee (Prashant). 🌟
The process consisted of 3 rounds:
| Duration: | 60 minutes |
| No. of Questions: | 3 |
| Difficulty: | Easy~Medium LC |
The assessment was on the easier end, in contrast to the insane difficulty levels of conventional companies.
I’d given Goldman Sachs assessment a short while ago.. the contradistinction of Easy/Medium was utterly apparent 🙄
This was the most interesting round among all.
| Duration: | 60 minutes |
| No. of interviewers: | 2 Engineers |
| Difficulty: | idk 😂 |
I didn’t discern what type of questions they could ask, so I had a breadth-first approach to preparation.. and a day before the interview I went through frequently asked interview questions.
However, as astonishing as it may sound, I wasn’t asked a single Data Structures/Algorithms/Core subjects/Development question!
Instead, I was evaluated on “how would you approach” type questions, for example, how would you approach:
…you get the idea.
This round wasn’t the most technically difficult - compared to ones I’d given before. But it was by far the most exploratory one. 🙇♂️
At the end of the interview, I received a dulcet feedback (hopefully 👀) from one of the interviewers, something nigh: that it’s good that I answered meticulously, but interns (in general) aren’t expected to respond in this technical depth.
I don’t think you can really “prepare” for these technical/behavioural questions; however, having a generic idea of company motto/aim really helps ~ try to plug ‘em in your responses! 🫡
| Duration: | 60 minutes |
| No. of Interviewers: | 1 Engineering Manager |
| Difficulty: | Moderate |
This round mostly revolved around my past experiences and projects. I believe this was to match candidate’s values & goals to the role they’re applying to, and to the company’s vision.
The interviewer came prepared with a set of questions, and at the end we had an informal chat about how I’ll be able to save money on food during office days. 😆
Seeing how managerial the technical round was, I had prepared for the actual managerial round in advance:
Mercari really focuses on their 3 core values (Remember I talked about them earlier? Yeah, those), and they’ve documented it all pretty well. I’d suggest anyone going for their interview to dig into their culture docs as a preparatory measure.
Another friend of mine (Anmol) had his interview process along the same timeline as mine; only he was applying for Android position, while I was in for Backend.
We both received our offer letters on the same day, sometime around first week of April. The entire interview process and results took around 3-4 weeks to complete. 😬
I managed to learn a few Japanese phrases, including the famous “arigato gozaimasu” (Thank you), some common nouns (for eg., “Toire” - Toilet 🙊) and most importantly “what-not-to-do” in Japan (for eg., you shouldn’t stick your chopsticks inside food/vertically, unless you’re at a funeral 😥).
A handsome amount of documents were required, all for a single piece of document known as COE (Certificate of Eligibility), which is issued by the Bureau of Immigration, Japan.
That document is so important, that the original one gets shipped from Japan to you, which is further required for your Visa application, immigration in Japan, residence card.. you get the point. 🤯
So apparently almost everybody in India got vaccinated with COVISHIELD or COVAXIN. But here’s me 💁♂️ thinking about better efficacy rate - had myself vaccinated with SPUTNIK V. 🫣
Two doses later, I realise my vaccination is not approved in 60% of countries out there (including Japan). 😢
So, I’d travel to Japan as an individual with no valid dose of vaccination, which meant extra measures such as a quarantine period of 7 days after travel, RTPCR tests both before and after the travel, etc.
After the entire visa process, the relocation folks booked my ticket in the largest airline of Japan, with cosy seats, staff, food, drinks and amenities! It never really felt like an economy class seat.
A tip if you’re travelling to Japan: Make sure to use the FastTrack service - It will make your check-in, screening, immigration, etc. much, much faster. 🤝
As another reminder of my denseness, I forgot to configure my internet settings for the new SIM I received from the company, and I went for groceries on my first day… without being connected to the web. 🥲
Thankfully, I asked a guy on the road, “Sumimasen, Supermarket wa doko desu ka.” (Excuse me, where is the supermarket), the response to which I did not understand 🥹, however he walked me directly to a supermarket.. it was almost a kilometre away, and he stayed with me throughout. 😳
I’ve had multiple such instances, where you can literally observe concern in their body language, and they all stuck with me until the very end! Respect well earned. ✅
The accommodation (provided by the company) is really well furnished, with a mesmerising view from the attached balcony.
The bathroom has utilities a person from a country like India would really appreciate. 🤭 (iykwim)
It’s located in a very convenient location, with 24x7 convenience stores, subways/metro stations, restaurants, temples, dispensaries/hospitals within walking distance.
I rented a bicycle, in a contract with accommodation folks, and I’ve been going on frequent rides at any point of day/night, as far as 10 km!
It really gives you a lot of flexibility and room to explore (even at 4AM in the night), and not get walk-tired. And it’s safe, with dedicated lanes and considerate people.
Food here is expensive. And if you choose home-delivery (UberEats shine here), you’ll literally eat through 3 days worth of food money. 🥶
Bento boxes, are much more economical, with full meals coming in lunch boxes you can heat up anytime in microwave and eat away.. that is, until you get bored of them. xD
Apart from this, there are regular team or onboarding lunches, wherein a fat amount is reimbursable by the company. 😬
You’re gonna have a hard, really hard time here in Japan if you’re a pure vegetarian.
Mercari has a YOUR CHOICE policy, wherein you can choose to work from the office or remotely from your home (in Japan). There’s also an option to work 10 hours a day (the login-logout system isn’t strict, however), so that you can work 4 days a week!
And then there are free vending machines, for drinks, equipment, and so on.
If you’re coming from the LinkedIn post, you probably have seen all these beautiful buildings, including the Skytree and the Tokyo Tower!
As I stated earlier, my interviews were moderate in terms of the technical challenge; however, they involved a lot of creativity, and having past internship experiences helped. 🙇♂ The interviewer took time to check out my website, which shows they care about the applicants.
Something I learnt from the interviews at Mercari:
You should never lowball your own skills, no matter how compelling your environment or the people in it are.
It has been my first international travel, my first time cycling through the streets alone at night, stopping wherever I want, to have a chat with strangers, to sit in a park, to try new food on my own!
Anmol, who was supposed to join with me had to defer his internship to next January due to an unexpected situation, so I came to Japan alone. 🙄
Now being alone in an entirely new country can get intimidating a bit, but the people here are very supportive. The accommodation folks even gave me a small tour of Tokyo, and I tried my first sushi with them! ❤️
I thank them, the interviewers, the TA team, the relocation team, my friends and everyone reading this right now. I hope you had a worthy time going through this write-up! I’ll end with meme about me visiting the office for the first time:
Dropping my socials in case you wanna have a chat (or have a doubt):
| Website: | aitikgupta.com - You’re here right now |
| LinkedIn: | linkedin.com/in/aitikgupta |
| GitHub: | github.com/aitikgupta |
| Instagram: | instagram.com/aitikgupta |
…you get the point, I go by @aitikgupta throughout the web! \o/
]]>To kick things off for the final report, here’s a meme to nudge about the previous blogs.
Matplotlib is a comprehensive library for creating static, animated, and interactive visualizations, which has become a de-facto Python plotting library.
Much of the implementation behind its font manager is inspired by W3C compliant algorithms, allowing users to interact with font properties like font-size, font-weight, font-family, etc.
By “not ideal”, I do not mean that the library has design flaws, but that the design was engineered in the early 2000s, and is now outdated.
(PS: here’s the link to my GSoC proposal, if you’re interested)
Overall, the project was divided into two major subgoals:
But before we take each of them on, we should get an idea about some basic terminology for fonts (which are a lot, and are rightly confusing)
The PR: Clarify/Improve docs on family-names vs generic-families brings about a bit of clarity about some of these terms. The next section has a linked PR which also explains the types of fonts and how that is relevant to Matplotlib.
An easy-to-read guide on Fonts and Matplotlib was created with PR: [Doc] Font Types and Font Subsetting, which is currently live at Matplotlib’s DevDocs.
Taking an excerpt from one of my previous blogs (and the doc):
Fonts can be considered as a collection of these glyphs, so ultimately the goal of subsetting is to find out which glyphs are required for a certain array of characters, and embed only those within the output.
PDF, PS/EPS and SVG output document formats are special, as in the text within them can be editable, i.e, one can copy/search text from documents (for eg, from a PDF file) if the text is editable.
The PDF, PS/EPS and SVG backends used to support font subsetting, only for a few types. What that means is, before Summer ‘21, Matplotlib could generate Type 3 subsets for PDF, PS/EPS backends, but it could not generate Type 42 / TrueType subsets.
With PR: Type42 subsetting in PS/PDF merged in, users can expect their PDF/PS/EPS documents to contains subsetted glyphs from the original fonts.
This is especially benefitial for people who wish to use commercial (or CJK) fonts. Licenses for many fonts require subsetting such that they can’t be trivially copied from the output files generated from Matplotlib.
Matplotlib was designed to work with a single font at runtime. A user could specify a font.family, which was supposed to correspond to CSS properties, but that was only used to find a single font present on the user’s system.
Once that font was found (which is almost always found, since Matplotlib ships with a set of default fonts), all the user text was rendered only through that font. (which used to give out “tofu” if a character wasn’t found)
It might seem like an outdated approach for text rendering, now that we have these concepts like font-fallback, but these concepts weren’t very well discussed in early 2000s. Even getting a single font to work was considered a hard engineering problem.
This was primarily because of the lack of any standardization for representation of fonts (Adobe had their own font representation, and so did Apple, Microsoft, etc.)
To migrate from a font-first approach to a text-first approach, there are multiple steps involved:
The very first (and crucial!) step is to get to a point where we have multiple font paths (ideally individual font files for the whole family). That is achieved with either:
Quoting one of my previous blogs:
Don’t break, a lot at stake!
My first approach was to change the existing public findfont API to incorporate multiple filepaths. Since Matplotlib has a very huge userbase, there’s a high chance it would break a chunk of people’s workflow:
Once we get a list of font paths, we need to change the internal representation of a “font”. Matplotlib has a utility called FT2Font, which is written in C++, and used with wrappers as a Python extension, which in turn is used throughout the backends. For all intents and purposes, it used to mean: FT2Font === SingleFont (if you’re interested, here’s a meme about how FT2Font was named!)
But that is not the case anymore, here’s a flowchart to explain what happens now:
With PR: Implement Font-Fallback in Matplotlib, every FT2Font object has a std::vector<FT2Font *> fallback_list, which is used for filling the parent cache, as can be seen in the self-explanatory flowchart.
For simplicity, only one type of cache (character -> FT2Font) is shown, whereas in actual implementation there’s 2 types of caches, one shown above, and another for glyphs (glyph_id -> FT2Font).
Note: Only the parent’s APIs are used in some backends, so for each of the individual public functions like
load_glyph,load_char,get_kerning, etc., we find the FT2Font object which has that glyph from the parent FT2Font cache!
Now that we have multiple fonts to render a string, we also need to embed them for those special backends (i.e., PDF/PS, etc.). This was done with some patches to specific backends:
With this, one could create a PDF or a PS/EPS document with multiple fonts which are embedded (and subsetted!).
From small contributions to eventually working on a core module of such a huge library, the road was not what I had imagined, and I learnt a lot while designing solutions to these problems.
…since all plots will work their way through the new codepath!
I think that single statement is worth the whole GSoC project.
For the sake of statistics (and to make GSoC sound a bit less intimidating), here’s a list of contributions I made to Matplotlib before Summer ‘21, most of which are only a few lines of diff:
| Created At | PR Title | Diff | Status |
|---|---|---|---|
| Nov 2, 2020 | Expand ScalarMappable.set_array to accept array-like inputs | (+28 −4) | MERGED |
| Nov 8, 2020 | Add overset and underset support for mathtext | (+71 −0) | MERGED |
| Nov 14, 2020 | Strictly increasing check with test coverage for streamplot grid | (+54 −2) | MERGED |
| Jan 11, 2021 | WIP: Add support to edit subplot configurations via textbox | (+51 −11) | DRAFT |
| Jan 18, 2021 | Fix over/under mathtext symbols | (+7,459 −4,169) | MERGED |
| Feb 11, 2021 | Add overset/underset whatsnew entry | (+28 −17) | MERGED |
| May 15, 2021 | Warn user when mathtext font is used for ticks | (+28 −0) | MERGED |
Here’s a list of PRs I opened during Summer’21:
From learning about software engineering fundamentals from Tom to learning about nitty-gritty details about font representations from Jouni;
From learning through Antony’s patches and pointers to receiving amazing feedback on these blogs from Hannah, it has been an adventure! 💯
Special Mentions: Frank, Srijan and Atharva for their helping hands!
And lastly, you, the reader; if you’ve been following my previous blogs, or if you’ve landed at this one directly, I thank you nevertheless. (one last meme, I promise!)
I know I speak for every developer out there, when I say it means a lot when you choose to look at their journey or their work product; it could as well be a tiny website, or it could be as big as designing a complete library!
I’m grateful to Maptlotlib (under the parent organisation: NumFOCUS), and of course, Google Summer of Code for this incredible learning opportunity.
Farewell, reader! :’)
Let’s say you asked Matplotlib to render a plot with some label containing 多个汉字 (multiple Chinese characters) in between your English text.
Or conversely, let’s say you use a Chinese font with Matplotlib, but you had English text in between (which is quite common).
Assumption: the Chinese font doesn’t have those English glyphs, and vice versa
With this short writeup, I’ll talk about how does a migration from a font-first to a text-first approach in Matplotlib looks like, which ideally solves the above problem.
Logically, the very first step to solving this would be to ask whether you have multiple fonts, right?
Matplotlib doesn’t ship CJK (Chinese Japanese Korean) fonts, which ideally contains these Chinese glyphs. It does try to cover most grounds with the default font it ships with, however.
So if you don’t have a font to render your Chinese characters, go ahead and install one! Matplotlib will find your installed fonts (after rebuilding the cache, that is).
This is where things get interesting, and what my previous writeup was all about..
Parsing the whole family to get multiple fonts for given font properties
To give you an idea about how things used to work for Matplotlib:
FT2Font is a matplotlib-to-font module, which provides high-level Python API to interact with a single font’s operations like read/draw/extract/etc.
Being written in C++, the module needs wrappers around it to be converted into a Python extension using Python’s C-API.
It allows us to use C++ functions directly from Python!
So wherever you see a use of font within the library (by library I mean the readable Python codebase XD), you could have derived that:
FT2Font === SingleFont
Things are be a bit different now however..
FT2Font is basically itself a wrapper around a library called FreeType, which is a freely available software library to render fonts.

In my initial proposal.. while looking around how FT2Font is structured, I figured:
Oh, looks like all we need are Faces!
If you don’t know what faces/glyphs/ligatures are, head over to why Text Hates You. I can guarantee you’ll definitely enjoy some real life examples of why text rendering is hard. 🥲
Anyway, if you already know what Faces are, it might strike you:
If we already have all the faces we need from multiple fonts (let’s say we created a child of FT2Font.. which only tracks the faces for its families), we should be able to render everything from that parent FT2Font right?
As I later figured out while finding segfaults in implementing this design:
Each FT2Font is linked to a single FT_Library object!
If you tried to load the face/glyph/character (basically anything) from a different FT2Font object.. you’ll run into serious segfaults. (because one object linked to an FT_Library can’t really access another object which has it’s own FT_Library)
// face is linked to FT2Font; which is
// linked to a single FT_Library object
FT_Face face = this->get_face();
FT_Get_Glyph(face->glyph, &placeholder); // works like a charm
// somehow get another FT2Font's face
FT_Face family_face = this->get_family_member()->get_face();
FT_Get_Glyph(family_face->glyph, &placeholder); // segfaults!
Realizing this took a good amount of time! After this I quickly came up with a recursive approach, wherein we:
std::vector<FT2Font *> fallback_listfallback_listA quick overhaul of the above piece of code^
bool ft_get_glyph(FT_Glyph &placeholder) {
FT_Error not_found = FT_Get_Glyph(this->get_face(), &placeholder);
if (not_found) return False;
else return True;
}
// within driver code
for (uint i=0; i<fallback_list.size(); i++) {
// iterate through all FT2Font objects
bool was_found = fallback_list[i]->ft_get_glyph(placeholder);
if (was_found) break;
}
With the idea surrounding this implementation, the Agg backend is able to render a document (either through GUI, or a PNG) with multiple fonts!

I’ve spent days at Python C-API’s argument doc, and it’s hard to get what you need at first, ngl.
But, with the help of some amazing people in GSoC community (@srijan-paul, @atharvaraykar) and amazing mentors, blockers begone!
Oh no. XD
Things work just fine for the Agg backend, but to generate a PDF/PS/SVG with multiple fonts is another story altogether! I think I’ll save that for later.
Before I answer that question, if you’re missing the context, check out my previous blog’s last few lines.. promise it won’t take you more than 30 seconds to get the whole problem!
With this short writeup, I intend to talk about what we did and why we did, what we did. XD
Ring any bells? Remember OS (Operating Systems)? It’s one of the core CS subjects which I bunked then and regret now. (╥﹏╥)
The wikipedia page has a 2-liner explaination if you have no idea what’s an Ostrich Algorithm.. but I know most of y’all won’t bother clicking it XD, so here goes:
Ostrich algorithm is a strategy of ignoring potential problems by “sticking one’s head in the sand and pretending there is no problem”
An important thing to note: it is used when it is more cost-effective to allow the problem to occur than to attempt its prevention.
As you might’ve guessed by now, we ultimately ended up with the not-so-clean API (more on this later).
The highest level overview of the problem was:
❌ fontTools -> buffer -> ttconv_with_buffer
✅ fontTools -> buffer -> tempfile -> ttconv_with_file
The first approach created corrupted outputs, however the second approach worked fine. A point to note here would be that Method 1 is better in terms of separation of reading the file from parsing the data.
ttconv_with_buffer is a modification to the original ttconv_with_file; that allows it to input a file buffer instead of a file-pathYou might be tempted to say:
“Well,
ttconv_with_buffermust be wrongly modified, duh.”
Logically, yes. ttconv was designed to work with a file-path and not a file-object (buffer), and modifying a codebase written in 1998 turned out to be a larger pain than we anticipated.
He even did, but the efforts to get it to production / or to fix ttconv embedding were ⋙ to just get on with the second method. That damn ostrich really helped us get out of that debugging hell. 🙃
Finally, we’re onto the second subgoal for the summer: Font Fallback!
To give an idea about how things work right now:
matplotlib.rcParams["font-family"] = ["list", "of", "font", "families"]
As soon as a font is found by iterating the font-family, all text is rendered by that and only that font.
You can immediately see the problems with this approach; using the same font for every character will not render any glyph which isn’t present in that font, and will instead spit out a square rectangle called “tofu” (read the first line here).
And that is exactly the first milestone! That is, parsing the entire list of font families to get an intermediate representation of a multi-font interface.
Imagine if you had the superpower to change Python standard library’s internal functions, without consulting anybody. Let’s say you wanted to write a solution by hooking in and changing, let’s say str("dumb") implementation by returning:
>>> str("dumb")
["d", "u", "m", "b"]
Pretty “dumb”, right? xD
For your usecase it might work fine, but it would also mean breaking the entire Python userbase’ workflow, not to mention the 1000000+ libraries that depend on the original functionality.
On a similar note, Matplotlib has a public API known as findfont(prop: str), which when given a string (or FontProperties) finds you a font that best matches the given properties in your system.
It is used throughout the library, as well as at multiple other places, including downstream libraries. Being naive as I was, I changed this function signature and submitted the PR. 🥲
Had an insightful discussion about this with my mentors, and soon enough raised the other PR, which didn’t touch the findfont API at all.
One last thing to note: Even if we do complete the first milestone, we wouldn’t be done yet, since this is just parsing the entire list to get multiple fonts..
We still need to migrate the library’s internal implementation from font-first to text-first!
But that’s for later, for now:

Well, it’s been a while since I last wrote. But I wasn’t spending time watching Loki either! (that’s a lie.)
During this period the project took on some interesting (and stressful) curves, which I intend to talk about in this small writeup.
The first week of coding period, and I met one of my new mentors, Jouni. Without him, along with Tom and Antony, the project wouldn’t have moved an inch.
It was initially Jouni’s PR which was my starting point of the first milestone in my proposal, Font Subsetting.
As was proposed by Tom, a good way to understand something is to document your journey along the way! (well, that’s what GSoC wants us to follow anyway right?)
Taking an excerpt from one of the paragraphs I wrote here:
Font Subsetting can be used before generating documents, to embed only the required glyphs within the documents. Fonts can be considered as a collection of these glyphs, so ultimately the goal of subsetting is to find out which glyphs are required for a certain array of characters, and embed only those within the output.
Now this may seem straightforward, right?
The glyph programs can call their own subprograms, for example, characters like ä could be composed by calling subprograms for a and ¨; or → could be composed by a program that changes the display matrix and calls the subprogram for ←.
Since the subsetter has to find out all such subprograms being called by every glyph included in the subset, this is a generally difficult problem!
Something which one of my mentors said which really stuck with me:
Matplotlib isn’t a font library, and shouldn’t try to be one.
It’s really easy to fall into the trap of trying to do everything within your own project, which ends up rather hurting itself.
To give an analogy, Google Docs try to do a lot of things with its platform, from basic text editing to full-fledged project management.
Compared with Notion, whose whole niche is to provide a platform for project management (among other things), some people tend to choose the latter for their specific needs.
Since this analogy holds true even for Matplotlib, it uses external dependencies like FreeType, ttconv, and newly proposed fontTools to handle font subsetting, embedding, rendering, and related stuff.
PS: If that font stuff didn’t make sense, I would recommend going through a friendly tutorial I wrote, which is all about Matplotlib and Fonts!
Matplotlib uses an external dependency ttconv which was initially forked into Matplotlib’s repository in 2003!
ttconv was a standalone commandline utility for converting TrueType fonts to subsetted Type 3 fonts (among other features) written in 1995, which Matplotlib forked in order to make it work as a library.
Over the time, there were a lot of issues with it which were either hard to fix, or didn’t attract a lot of attention. (See the above paragraph for a valid reason)
One major utility which is still used is convert_ttf_to_ps, which takes a font path as input and converts it into a Type 3 or Type 42 PostScript font, which can be embedded within PS/EPS output documents. The guide I wrote (link) contains decent descriptions, the differences between these type of fonts, etc.
Why do we need to? Type 42 subsetting isn’t really supported by ttconv, so we use a new dependency called fontTools, whose ‘full-time job’ is to subset Type 42 fonts for us (among other things).
It provides us with a font buffer, however ttconv expects a font path to embed that font
Easily enough, this can be done by Python’s tempfile.NamedTemporaryFile:
with tempfile.NamedTemporaryFile(suffix=".ttf") as tmp:
# fontdata is the subsetted buffer
# returned from fontTools
tmp.write(fontdata.getvalue())
# TODO: allow convert_ttf_to_ps
# to input file objects (BytesIO)
convert_ttf_to_ps(
os.fsencode(tmp.name),
fh,
fonttype,
glyph_ids,
)
But this is far from a clean API; in terms of separation of *reading* the file from *parsing* the data.
What we ideally want is to pass the buffer down to convert_ttf_to_ps, and modify the embedding code of ttconv (written in C++). And here we come across a lot of unexplored codebase, which wasn’t touched a lot ever since it was forked.
Funnily enough, just yesterday, after spending a lot of quality time, me and my mentors figured out that the whole logging system of ttconv was broken, all because of a single debugging function. 🥲
This is still an ongoing problem that we need to tackle over the coming weeks, hopefully by the next time I write one of these blogs, it gets resolved!
Again, thanks a ton for spending time reading these blogs. :D
With this small writeup, I intend to talk about everything before that day, my experiences, my journey, and the role of Matplotlib throughout!
I am a third-year undergraduate student currently pursuing a Dual Degree (B.Tech + M.Tech) in Information Technology at Indian Institute of Information Technology, Gwalior.
During my sophomore year, my interests started expanding in the domain of Machine Learning, where I learnt about various amazing open-source libraries like NumPy, SciPy, pandas, and Matplotlib! Gradually, in my third year, I explored the field of Computer Vision during my internship at a startup, where a big chunk of my work was to integrate their native C++ codebase to Android via JNI calls.
To actuate my learnings from the internship, I worked upon my own research along with a friend from my university. The paper was accepted in CoDS-COMAD’21 and is published at ACM Digital Library. (Link, if anyone’s interested)
During this period, I also picked up the knack for open-source and started glaring at various issues (and pull requests) in libraries, including OpenCV [contributions] and NumPy [contributions].
I quickly got involved in Matplotlib’s community; it was very welcoming and beginner-friendly.
Fun fact: Its dev call was the very first I attended with people from all around the world!
We all mess up, my very first PR to an organisation like OpenCV went horrible, till date, it looks like this:

In all honesty, I added a single commit with only a few lines of diff.
However, I pulled all the changes from upstream
masterto my working branch, whereas the PR was to be made on3.4branch.
I’m sure I could’ve done tons of things to solve it, but at that time I couldn’t do anything - imagine the anxiety!
At this point when I look back at those fumbled PRs, I feel like they were important for my learning process.
Fun Fact: Because of one of these initial contributions, I got a shiny little badge [Mars 2020 Helicopter Contributor] on GitHub!

It was around initial weeks of November last year, I was scanning through Good First Issue and New Feature labels, I realised a pattern - most Mathtext related issues were unattended.
To make it simple, Mathtext is a part of Matplotlib which parses mathematical expressions and provides TeX-like outputs, for example:

I scanned the related source code to try to figure out how to solve those Mathtext issues. Eventually, with the help of maintainers reviewing the PRs and a lot of verbose discussions on GitHub issues/pull requests and on the Gitter channel, I was able to get my initial PRs merged!
Most of us use libraries without understanding the underlining structure of them, which sometimes can cause downstream bugs!
While I was studying Matplotlib’s architecture, I figured that I could use the same ideology for one of my own projects!
Matplotlib uses a global dictionary-like object named as rcParams, I used a smaller interface, similar to rcParams, in swi-ml - a small Python library I wrote, implementing a subset of ML algorithms, with a switchable backend.
It was around January, I had a conversation with one of the maintainers (hey Antony!) about the long-list of issues with the current ways of handling texts/fonts in the library.
After compiling them into an order, after few tweaks from maintainers, GSoC Idea-List for Matplotlib was born. And so did my journey of building a strong proposal!
The aim of the project is divided into 3 subgoals:
Font-Fallback: A redesigned text-first font interface - essentially parsing all family before rendering a “tofu”.
(similar to specifying font-family in CSS!)
Font Subsetting: Every exported PS/PDF would contain embedded glyphs subsetted from the whole font.
(imagine a plot with just a single letter “a”, would you like it if the PDF you exported from Matplotlib to embed the whole font file within it?)
Most mpl backends would use the unified TeX exporting mechanism
Mentors Thomas A Caswell, Antony Lee, Hannah.
Thanks a lot for spending time reading the blog! I’ll be back with my progress in subsequent posts.
Data Authenticity on social media platforms these days is a joke. Plagiarism is widespread, as it takes almost no efforts to re-post someone else’s post without their knowledge.
And that is precisely where SocioMark fits in.
Imagine a social media platform that lets you upload images and secures them by embedding a personalised hash - such that your asset will always remain your asset, regardless of who posts it!
To build such a platform, our team (Me, Bodhisha Thomas, Deepak Agrawal and Sumi Kolli) decided to collaborate over the last sprint of the MLH-Fellowship.
Like any other social media platform, SocioMark provides users ability to:
However, apart from these generic features, one special feature that SocioMark provides is:
When a user creates a post with an image asset, the user’s unique id from the database is encrypted via SHA and a unique 256-bit binary number is generated, which is ultimately embedded onto the image.
Watermarking an image (embedding some information) can be done via 2 ways:
In the spatial domain, the classic LSB supports a large amount of watermark information and has little impact on the original image. However, the anti-interference ability is relatively poor and cannot resist image cropping, scaling and jpg compression.
In the frequency domain, such as DCT and DWT, the algorithms have strong anti-interference ability.
Which means even if we attack the image by compressing/adding artifacts to the image - the information embedded in the image will still retain!
To give birth to this platform, we used FARM Stack:-
(Fa)stAPI - Server, (R)eactJS - Client, (M)ongoDB - Database
Being a Python backend and a Javascript frontend, both are deployed and maintained separately on Heroku and Netlify respectively.
Cloudinary - The database to store the imagesMongoDB Atlas - The database to store the users, posts, comments and likes
The backend endpoints, their routes, their model schemas, and their controllers are all implemented in Python using FastAPI.
| Description | Type | Link |
|---|---|---|
| Demo | YouTube | youtu.be/1J6-tyKmhdc/ |
| Frontend | Netlify | sociomark.netlify.app/ |
| Backend | Heroku | sociomark-backend.herokuapp.com/ |
| Submission | Devpost | devpost.com/software/sociomark/ |
| Source Code | GitHub | MLH-Fellowship/SocioMark/ |
SocioMark is a Progressive Web Application (it can be installed on devices!), is completely Responsive (it works on mobile devices!) - and ensures Data Authenticity throughout the platform.
With more than ~60 closed Pull Requests and ~70 closed Issues across 4 core developers and 5 contributors, the repository is open sourced at MLH-Fellowship’s GitHub.
]]>There are several utilities from GitHub that makes collaboration easy, GitHub Projects is one of them.
Currently, there is no UI-based extension that integrates GitHub Projects in VSCode. Hence, our team (Me, Dean Gladish, Samuel Yuan and Shrill Shrestha) decided to make one.
GitHub Projects are divided into 3 scopes:
One can create Kanban boards with any of these scopes to track the progress of a project. A typical card maintained on a project board can contain anything from a simple note to linked Issues and Pull Requests.
The extension we built communicates with GitHub’s backend using GraphQL API - Queries and Mutations, to render a WebView built by Svelte on VSCode with it’s native UI.
The result is an integration of realtime communication between VSCode native UI and GitHub Projects. It allows a user to:
| Description | Type | Link |
|---|---|---|
| Demo | YouTube | youtu.be/MycrfrHHz18/ |
| Extension | Visual Studio Marketplace | Pod212.vscode-github-projects/ |
| Submission | Devpost | devpost.com/software/vscode-github-projects/ |
| Source Code | GitHub | MLH-Fellowship/vscode-github-projects/ |
The repository is open sourced at MLH-Fellowship’s GitHub.
]]>swi-ml is a small lightweight Python library, which implements a subset of classical machine learning algorithms, with a twist - it has a switchable backend!
from swi_ml import set_backend
# numpy backend (CPU)
set_backend("numpy")
# cupy backend (GPU)
set_backend("cupy")
NumPy offers comprehensive mathematical functions, random number generators, linear algebra routines, Fourier transforms, and more. It is the backbone for many such libraries, like scikit-learn.
But, most of its code is in serial order.
numpyis primarily designed to be as fast as possible on a single core, and to be as parallelizable as possible if you need to do so.
Moreover, vanilla NumPy cannot accelerate computing on a GPU.
CuPy is an open-source array library accelerated with NVIDIA CUDA, which speeds up some operations more than 100X.
“CuPy’s interface is highly compatible with NumPy; in most cases it can be used as a drop-in replacement.” - So why not use this and create a small library which implements a domain-problem (machine learning in this case) and benefit from both libraries at a single interface?
It was built in a duration of a month, where I mostly learnt:
print() statement!)singleton Backend (with correct raises and runtime imports)swi-ml is published to PyPI at this URL: https://pypi.org/project/swi-ml/
So installing it is as simple as:
pip install swi-ml
Or, via GitHub:
pip install git+https://github.com/aitikgupta/swi-ml
Except NumPy, there’s no hard-dependency!
Although, to use the GPU-accelerated backend, a working installation of CuPy (install guide) is required.
Other than this, some plot functions might require a working installation of matplotlib, but it will be a runtime-dependency soon (see Roadmap).
Code is open sourced at GitHub, one can find many, many comments within the library.
There was a time in developing cycles, when I decided to change the name of the library - cherry points if one can figure out the previous name! (HINT: It is close to an amazing library by RapidsAI, and has a commit dedicated to it)
]]>