Nono.MA

APRIL 3, 2020

Are you into #ComputationalDesign?

Subscribe now to @garciadelcast's Live Stream.

Happening today, Friday, April 3, 2020, at 10 am EST!

APRIL 3, 2020

Just yesterday, Google announced a new challenge.

Reconstructing 3D objects and buildings from a series of images is a well-known problem in computer vision, known as Structure-from-Motion (SfM). It has diverse applications in photography and cultural heritage preservation (e.g., allowing people to explore the sculptures of Rapa Nui in a browser) and powers many services across Google Maps, such as the 3D models created from StreetView and aerial imagery. In these examples, images are usually captured by operators under controlled conditions. While this ensures homogeneous data with a uniform, high-quality appearance in the images and the final reconstruction, it also limits the diversity of sites captured and the viewpoints from which they are seen. What if, instead of using images from tightly controlled conditions, one could apply SfM techniques to better capture the richness of the world using the vast amounts of unstructured image collections freely available on the internet?

[…]

We hope this benchmark, dataset and challenge helps advance the state of the art in 3D reconstruction with heterogeneous images. If you’re interested in participating in the challenge, please see the 2020 Image Matching Challenge website for more details.

APRIL 1, 2020

#HouseGAN

Meet #HouseGAN: A relational generative adversarial network for graph-constrained house layout generation by Nelson Nauata & Chin-Yi Cheng at Autodesk Research in 2019.

Generate house layouts from architectural constraint graphs.

📝Paper → https://arxiv.org/abs/2003.06988
🧠Code → Coming soon!

This paper proposes a novel graph-constrained generative adversarial network, whose generator and discriminator are built upon relational architecture. The main idea is to encode the constraint into the graph structure of its relational networks. We have demonstrated the proposed architecture for a new house layout generation problem, whose task is to take an architectural constraint as a graph (i.e., the number and types of rooms with their spatial adjacency) and produce a set of axis-aligned bounding boxes of rooms. We measure the quality of generated house layouts with the three metrics: the realism, the diversity, and the compatibility with the input graph constraint. Our qualitative and quantitative evaluations over 117,000 real floor plan images demonstrate that the proposed approach outperforms existing methods and baselines. We will publicly share all our code and data.

MARCH 31, 2020

Pretty impressed by ImgIX's JSON format. Long story short, it provides a JSON metadata file for each resource you are serving via ImgIX (say, an image or a video) as in the example below just by appending fm=json to any image request.

For this image.

https://nono.imgix.net/img/u/profile-nono-ma.jpg

You'd load the JSON at.

https://nono.imgix.net/img/u/profile-nono-ma.jpg?fm=json

What's nice is that with the imgix.js JavaScript library you can fetch the JSON file for each picture and—before loading any image data—decide how to deliver the image. In this CodePen provided by ImgIX, they crop a set of images to fit a certain aspect ratio (which ends up saving data as they cropped bits of each image are never loaded) avoiding also having to play with image background CSS tricks in order to fit an image to a given aspect ratio (as the image already has it!).

{
    "Exif": {
        "PixelXDimension": 1500,
        "DateTimeDigitized": "2019:11:20 10:43:28",
        "PixelYDimension": 1500,
        "ColorSpace": 65535
    },
    "Orientation": 1,
    "Output": {},
    "Content-Type": "image\/jpeg",
    "JFIF": {
        "IsProgressive": true
    },
    "DPIWidth": 144,
    "Content-Length": "180595",
    "Depth": 8,
    "ColorModel": "RGB",
    "DPIHeight": 144,
    "TIFF": {
        "ResolutionUnit": 2,
        "DateTime": "2019:11:20 11:17:40",
        "Orientation": 1,
        "Software": "Adobe Photoshop CC 2019 (Macintosh)",
        "YResolution": 144,
        "XResolution": 144
    },
    "PixelWidth": 1500,
    "PixelHeight": 1500,
    "ProfileName": "Display"
}

And here's the JavaScript included in that CodePen that does all the magic.

// Demonstrate the use of the `fm=json` parameter to resize images
// to a certain aspect ratio, using ES6.

let ratio = 16 / 9;
let maxSize = 300;

let placeImages = function () {
    jQuery('.imgix-item').each((i, value) => {
        let $elem = jQuery(value);
        // We pull down the image specific by the 'data-src' attribute
        // of each .imgix-item, but append the "?fm=json" query string to it.
        // This instructs imgix to return the JSON Output Format instead of 
        // a manipulated image.
        let url = new imgix.URL($elem.attr('data-src'), { fm: "json" }).getUrl();

        jQuery.ajax(url).success((data) => {
            let newWidth, newHeight;

            // Next, we compute the new height/width params for 
            // each of our images.
            if (data.PixelHeight > data.PixelWidth) {
                newHeight = maxSize;
                newWidth = Math.ceil(newHeight / ratio);
            } else {
                newWidth = maxSize;
                newHeight = Math.ceil(newWidth / ratio);
            }

            // Now, we apply these to our actual images, setting the 'src'
            // attribute for the first time.
            $elem.get(0).src = new imgix.URL($elem.attr('data-src'), {
                w: newWidth,
                h: newHeight,
                fit: "crop"
            }).getUrl();
        })
    });
}

jQuery(document).ready(placeImages);

MARCH 31, 2020

From a parallel universe

Events kept popping up on my phone throughout March.

In that parallel universe, I would had a hectic month of March.

Two weeks ago (on March 16, 2020) Daniel Natoli and I would have presented and screened Sisyphus at Antonio Banderas' new theater as part of 2020 Málaga Film Festival.

I would have delivered an Autodesk talk in Helsinki but I didn't fly.

I would have talked at ALGOMAD Madrid but I didn't catch that train.

I would hike Macchu Picchu next week but I won't board that plane.

Yet, I'm lucky enough to be able to continue living a fairly similar lifestyle to how I've been living for the past year: I plug my laptop to a screen and code long hours, then connect with a remote team of developers in the afternoon; I sketch and write and podcast1 in the evening; then rinse and repeat.


  1. Psst! I just released Getting Simple's episode with Scott MitchellExperimentation in the Arena—in which Scott jumps in time to dissect his own experimentation life philosophy, his efforts to remove creative friction, and his worldview. 

MARCH 30, 2020

gs -dNOPAUSE -sDEVICE=pdfwrite \
-sOUTPUTFILE=/output/path/combined.pdf \
-dBATCH /input/path/to/pdfs/*.pdf

MARCH 24, 2020

Here's something I learned about Amazon SageMaker today at work.

You can create notebook instances with different instance types (say, ml.t2.medium or ml.p3.2xlarge) and use a set of kernels that have been setup for you. These are conda (Anaconda) environments exposed as Jupyter notebook kernels that execute the commands you write on the Python notebook.

What I learned today that I didn't know is that you can create your own conda environment and expose them as kernels so you're not limited to run with the kernels offered by Amazon AWS.

This is the sample environment I setup today. These commands should be run on a Terminal window in a SageMaker notebook but they most likely can run on any environment with conda installed.

# Create new conda environment named env_tf210_p36
$ conda create --name env_tf210_p36 python=3.6 tensorflow-gpu=2.1.0 ipykernel tensorflow-datasets matplotlib pillow keras

# Enable conda on bash
$ echo ". /home/ec2-user/anaconda3/etc/profile.d/conda.sh" >> ~/.bashrc

# Enter bash (if you're not already running in bash)
$ bash

# Activate your freshly created environment
$ conda activate env_tf210_p36

# Install GitHub dependencies
$ pip install git+https://github.com/tensorflow/examples.git

# Now you have your environment setup - Party!
# ..

# When you're ready to leave
$ conda deactivate

How do we expose our new conda environment as a SageMaker kernel?

# Activate the conda environment (as it has ipykernel installed)
$ conda activate env_tf210_p36

# Expose your conda environment with ipykernel
$ python -m ipykernel install --user --name env_tf210_p36 --display-name "My Env (tf_2.1.0 py_3.6)"

After reloading your notebook instance you should see your custom environment appear in the launcher and in the notebook kernel selector.

What if you don't want to repeat this process over and over and over?

You can create a lifecycle configuration on SageMaker that will run this initial environment creation setup every time you create a new notebook instance. (You create a new Lifecycle Configuration and paste the following code inside of the Create Notebook tab.)


#!/bin/bash

set -e

# OVERVIEW
# This script creates and configures the env_tf210_p36 environment.

sudo -u ec2-user -i <<EOF

echo ". /home/ec2-user/anaconda3/etc/profile.d/conda.sh" >> ~/.bashrc

# Create custom conda environment
conda create --name env_tf210_p36 python=3.6 tensorflow-gpu=2.1.0 ipykernel tensorflow-datasets matplotlib pillow keras -y

# Activate our freshly created environment
source /home/ec2-user/anaconda3/bin/activate env_tf210_p36

# Install git-repository dependencies
pip install -q git+https://github.com/tensorflow/examples.git

# Expose environment as kernel
python -m ipykernel install --user --name env_tf210_p36 --display-name My_Env_tf_2.1.0_py_3.6

# Deactivate environment
source /home/ec2-user/anaconda3/bin/deactivate

EOF

That way you won't have to setup each new notebook instance you create. You'll just have to pick the lifecycle you just created. Take a look at Amazon SageMaker notebook instance Lifecycle Configuration samples.

MARCH 24, 2020

News from the future

While I was taking part on an online architecture school review last week—with more than twenty students and review guests confined to their bedrooms and talking into a Zoom window through their webcams—Kyle Steinfeld mentioned how we, in Spain, were "in the future, five days ahead of us [in California]."1

None of us saw it coming. It was a foreign problem seen from the distance and read on a screen, which the entire world thought was an issue for Wuhan to deal with. Just a few weeks later there are more than 160 countries fighting against the virus.2

The amount of confirmed cases and the ratio of deaths to recoveries reported by each country depends on its testing strategy. I'd be curious to know which countries weren't added earlier to the map just because they took longer to start testing for the virus.

We usually don't act until something affects us directly (may it be us as individuals, as family, as a country, or the world).

It's the politicians in the end who dictate what we have to do—whether we need to stay at home or who should continue going to work or whether it's ok to go walk your dog or buy bread.

All that's left for us is to applaud, complain, or share the meme of the moment, to laugh at how surreal the situation we're living is at the same time that many people still don't think these agreements apply to them.

Stay home. We can do it!

That's my rant.


  1. The work Kyle and his students are doing at Berkeley training machine learning models to generate architectural sketches is worth seeing. You can take a look at Drawn, Together

  2. Here's an animation of how COVID-19 keeps ramping up

MARCH 20, 2020

Maker.js: Parametric CNC Drawings Using JavaScript

Microsoft recently open sourced, twenty five days ago, Maker.js — a JavaScript library to create drawings on the browser for CNC and laser cutting.

I love the playground site they made to share parametric scripts (say, of a smiley face, a hello, world text, a floor plan, and more). See all demos.

From their website:

  • Drawings are a simple JavaScript object which can be serialized / deserialized conventionally with JSON. This also makes a drawing easy to clone.
  • Other people's Models can be required the Node.s way, modified, and re-exported.
  • Models can be scaled, distorted, measured, and converted to different unit systems.
  • Paths can be distorted.
  • Models can be rotated or mirrored.
  • Find intersection points or intersection angles of paths.
  • Traverse a model tree to reason over its children.
  • Detect chains formed by paths connecting end to end.
  • Get the points along a path or along a chain of paths.
  • Easily add a curvature at the joint between any 2 paths, using a traditional or a dogbone fillet.
  • Combine models with boolean operations to get unions, intersections, or punches.
  • Expand paths to simulate a stroke thickness, with the option to bevel joints.
  • Outline model to create a surrounding outline, with the option to bevel joints.
  • Layout clones into rows, columns, grids, bricks, or honeycombs.

Via @alfarok's GitHub stars.

MARCH 18, 2020

Here are some loose thoughts on what I've been tinkering with for the past months or years.

As of lately, I've been working on Folio—the content-management system this site runs on—to add new features, fix bugs here and there, and make it easier to deploy it across multiple websites—including mine and client sites. The system keeps getting better and better and I repeatedly ask myself whether I'm reinventing the wheel in many areas. I make use of great third-party packages developed with care and thoughtfulness by other developers. It's incredible when they work but awful when other developers stop updating and your code breaks. I now pay more and more attention to those GitHub starts (★) and pick carefully what packages to implement. Software rots.

I've learned a lot about managing my own Linux machines—both from scratch or from an existing image—to have a new site ready within minutes (at least, when I don't hit an unknown problem that steals a few hours from my day). I'm mainly deploying apps with Nginx and Laravel but I've also learned to run and deploy Node.js apps (with PM2), how to serve Docker images, or how to run Python and Golang programs.

I'm trying to thoroughly document all the troubleshooting I go through to not have to dig the internet to fix a bug I've fixed some time before. While it's obvious how to fix a bug you encountered yesterday, some bugs don't show up again for long, and you can save hours of work by keeping good notes.

A recent practice I've started playing with is creating automation files. I'm slowly getting acquainted with "Makefiles," text files that describe commands which are a list of command calls that will be executed after you type make command-name on your Terminal. These commands not only run on Linux machines but on the macOS terminal, so I can run most of my automation scripts both on the desktop and Linux servers. Here's a sample Makefile to setup a Digital Ocean droplet.

I build Folio mainly for myself. There are many systems like it but this one is entirely built by me, and it helps me learn new programming features as well as modern patterns and techniques by browsing other people's code when I use their packages. Many will hate Folio—simply because it runs on PHP—but I believe Laravel is making this programming language great again. (Trust me, I did PhpNuke sites back in 2003 and this is light years ahead.) Laravel feels like an updated version of Ruby on Rails.

I'm migrating most of my sites to Digital Ocean. Their droplet system (without hidden costs) is great. I'm still to see where to put Getting Simple's podcast audio files. A powerful package by the Spatie team makes backing up websites a breeze: I can schedule automatic database and file backups at desired time intervals, even uploading them to multiple disks (such as Digital Ocean Spaces, Dropbox, or Amazon S3).

I've recently started using Imgix to distribute my images and remove that load from website servers. The image-processing REST API they offer makes is flexible and removes many headaches and time lost manually editing images with Photoshop or other applications, might it be to apply simple effects, sharpening, resizing, or even adding watermarks or padding. And their CDN makes their distribution faster.

I rely less and less on TypeKit for web fonts, as I either serve the font files or use Google Fonts. There are also beautiful typefaces from type foundries that I might use soon. (Milieu Grotesque comes to mind.)

A big highlight (that sadly only runs on macOS) is Laravel Valet. After spending months learning how to configure Nginx blocks and crashing the system multiple times I found this simple tool that handles everything for you. There's a bit of reading to do to fully understand what it does but I'd summarize its benefits to two commands: valet link and valet unlink. With one command your computer serves a PHP app at http://app-name.test from the directory in which you run the command and the second command stops serving it. You can quickly register a folder to serve an app (say, with valet link nono) and quickly go to its URL to test the site locally (at http://nono.test). Behind the scenes, Valet uses dnsmasq, php, and nginx. Not having to deal with them on a daily basis makes things easy (even though I like to learn what's behind these systems and how to do it the manual way in case there's a need for it).

Another thing I'm loving are Cron jobs. They can be set either on Linux (as I do on Digital Ocean) or macOS with crontab -e. You also have to learn a bit about how Cron works but the short story is that it lets you schedule tasks: command executions at whatever time interval (or time of the day) you want. For instance, * * * * * curl https://google.com would ping Google every minute. And you can go from every minute to certain times of the day or fractions of the hour. Laravel copes with it by letting you schedule commands with a clean, high-level API (for instance, ->everyMinute() or ->dailyAt('17')). All you do is set a Cron job to execute the Laravel schedule every minute and Laravel decides what commands to run when.

Last but not least, I'd highlight the importance of logging. Most environments have ways to log executions and errors and this is the easiest way to find out what's breaking your system. I've added a route in Folio's administration in order to visualize logs from anywhere and, at a lower level, Nginx lets you log access and errors as well.

I'm constantly learning, and Folio and my website are my playground.

As I started saying, these are loose thoughts of many of the tech I've been exploring over the past year. I'm also learning about Docker, TensorFlow, Runway, and much more, and frequently keeping my notes on Dropbox Paper. Some of my experiments are kept in the open on GitHub, and I've recently started sharing what I'm learning on this YouTube playlist.

What are you tinkering with?

MARCH 18, 2020

try:
    %tensorflow_version 2.x
except Exception:
  pass

import tensorflow as tf

Note that %tensorflow_version is only available in Colab and not in regular Python.

MARCH 17, 2020

Taking time to make decisions: Our new mampara

Eleven months after moving to Panaderos, on January 16, 2020, we were able to shower for the first time with our new mampara in place. (That's how we say "shower screen" here in Spain.) Alex and Lolo, from Bauhaus, installed it the day before. We had to wait twenty four hours for the silicone sealing to dry out before we could use it.

Showering without splashing water out (and staying warm) was a joyous moment. A luxury we grew up with for around $600.

But why did we wait for almost a year to have it installed if the installation took just one hour?

We didn't know what we wanted when we first moved. We spent months evaluating different options to end up giving into an idea we didn't want to settle for initially—building an opaque, perpendicular extension to one of the existing bathroom walls which, after all, doesn't look that bad.


Farsighted is a book about making decisions, about why it takes us so long to make them and practices to end up making the best possible choices in a world in which we won't ever know the correct answer, written by Steven Johnson.

With experience, (some) decisions are faster. Others will always take long. And other won't ever be made.

In my own experience, I've discover that what works for me is letting things sit over days, weeks, or even months, and let my mind evaluate the different possibilities.

Still, no matter how long you take to make a decision, you won't ever know whether it was the right choice.

MARCH 10, 2020

What do apples and software have in common?

Software, as fruit, rots. If you leave it there for long enough it will go bad, and programs stop working. When the dependencies of a program and the environment in which it runs get updated, different pieces of code break. You need to re-write parts of it to make it compatible with the latest "breaking changes."

Code maintenance is a labor of love—and even more when your software is open source as other programs might rely on it.

The biggest platform to share and find open-source software is GitHub. The "stars" of a project are the code-equivalent to Instagram or Facebook likes, usually indicative of how likely a repository of code is to withstand the test of time, as they often represent not only the size of a project's community but how quickly code gets fixed when it breaks.

MARCH 3, 2020

The windy road to Korakonisi

Mikela was holding the wheel. Aziz was her co-pilot.

They drove her car to Zakynthos all the way from Athens.

The Mediterranean sea was in front of us as we descended a windy road among bushes.

We'd rented an AirBnb to stay in Drosia, the top-floor of a two-story house of the nicest Greek family.

I still remember the joy I got when Aziz and Mikela showed up. I hand't seen them since our last trip to the snowy mountains of New England, where we went snowboarding and skiing with our squad.

This time, far from Cambridge, we wore swimsuits and sunglasses.

I left my rental car at the AirBnb and joined them in Mikela's car. As we approached the sea through a bumpy and windy road I started getting dizzy while trying to capture this scene.

We finally arrived at Korakonisi's rocky beach, and set camp in front of the immense natural arch, which I recall climbing up to a little wooden hut with Captain Gabour and Giorgos later that day.

Our only concern was to sunbathe, swim, climb, and chat.

Who wouldn't go back there?

FEBRUARY 26, 2020

I was getting this error in Laravel as I created a new app using the latest version (that is 6.2). Not sure why, the class would work locally but not remotely (on a deployment running in Ubuntu 18.04.3 on DigitalOcean to be precise).

I was using \ResourceBundle::getLocales('') to get a list of valid locales present on a website and then using in_array($needle, $array) to check whether a given locale is valid in PHP.

Here's how I fixed it.

  • composer require symfony/intl to install Symfony's Intl component.
  • Replaced my in_array calls with \Symfony\Component\Intl\Locales::exists($translation).

FEBRUARY 25, 2020

We are out of face masks

Four days before the Chinese New Year, Dr. Guan Yi went to Wuhan among billions of Chinese people on their way to celebrate the year of the Rat, but the reason for his trip was different.1

The Chinese took 3 billion trips in a forty-day period surrounding January 252, the Chinese New Year and, last time I checked, China had locked down five different cities amounting to twenty-something million people (which is half the population of Spain).3


A few days later, on January 27, Sanjay sat next to me on a flight from Paris to Toronto. Coming all the way from India to spend four weeks in Canada with his son, Sanjay was wearing a face mask for prevention, and I spotted two other people wearing face masks as I changed flights in Charles de Gaulle that same day.


Coming back to Dr. Guan Yi, he traveled with his team to identify the germ that originated Coronavirus' outbreak1. They had successfully identified the Coronavirus that caused 2002–2003's SARS epidemic. This time, when Dr. Guan and his team arrived to the market where many infections had been traced back to, he found no trace of the virus. The government had disinfected it getting rid of any evidence.


At the moment of this writing, there are seventy-six thousand confirmed cases4. I wonder if there have been any previous viruses tracked so closely. Yet, only 0.004% of the reported deaths have occurred outside of China.

China quickly ran out of face masks, and I gave up searching for face masks in Brooklyn. While the media does its job to keep us alert, rumors say that China has been playing down its numbers. I have no idea.

What's true is that Coronavirus is (or has been) in your mind. It's not only a virus that spreads but viral news.


  1. At the moment of my visit to Coronavirus Death Toll Climbs in China, and a Lockdown Widens (2020) on The New York Times, the alarming headline said "25 people [had] died and more than 800 [had] been sickened by the mysterious illness."  

  2. More Chinese cities shut down, New Year events cancelled as deadly virus spreads (2020). France 24

  3. CNN Live news (Jan 24, 2020). CNN

  4. You can check the reported cases live. Coronavirus COVID-19 Global Cases by Johns Hopkins CSSE. 

FEBRUARY 21, 2020

In C#, .NET, and Visual Studio, you can use the Random Class to generate random numbers.

First, you create a random number generator.

var random = new Random(1); // where 1 is our seed

Then you request the next random number (or next random double).

// Next random number
var aRandomNumber = random.Next();

// Next random double
var aRandomDouble = random.NextDouble();

FEBRUARY 19, 2020

Nodi: An Online Node-based Geometry Design Tool and Platform

Nodi is a promising web-based visual programming environment that, at first sight, reminds me of Grasshopper and can be used on a browser tab.

And, while writing these lines, I checked their home page.

Node is an online node-based geometry design tool and social development environment. […] You can create a model with a feeling of operation like Grasshopper and Dynamo.

Haven't looked in depth yet, but it seems to support some 2d and 3d geometry, math, exporting to formats like obj and dxf and stl, and much more.

I'll close with a Twitter quote from Masatatsu Nakamura.

It feels very intuitive to a Grasshopper user, but is built entirely on web tech.

FEBRUARY 18, 2020

Thirty

I was born on a day of rest—on a Sunday morning at 10:50 am.

Today, I'm turning thirty years old.

I've been alive for 10,957 days (1,565 weeks and 2 days) and, looking at it that way, it might as well make sense to celebrate my 11,000th day on April 1, 2020. Back then in 1990, when I was born, my sister was 1,224 days old. 1

What would you tell your twenty-year-old self? I wanted to ask myself this question today, as I often ask others on the podcast. Let's see what I came up with.

  • Friends and family are more important than anything else.
  • Side projects are as important (or even more) than school and work. They define who you really are and give meaning to your life.
  • Document everything as you do it (and write everyday). You'll love being able to look back at what you're doing today when you're older.

It's hard to find meaning and purpose, and extremely easy to get caught on doing one thing after the other, spanning across years—if not decades—without asking yourself the real question, so I'll keep asking myself, day after day: What do you want to be when you grow up?


  1. As I used to do before on Wolfram Alpha, you can now Google time spans and get the amount of days, like, for instance, days between 1990-02-18 and today

FEBRUARY 11, 2020

A chair and a table

I grew up sitting at the table to eat—often half-sitting with one knee, ready to flee to my computer or my toys.

A year ago, right when we moved into our new place, we were slow to acquire new furniture. For a few days, maybe weeks, we'd do picnics in the living room, waiting for our table to arrive. We'd eat on top of a blanket. We'd eat on the floor. The picnics were fun.

We then bought a table and four chairs. The picnic season was over.


I like to test myself by relocating objects to a different place and paying attention to when the next time I want to use them is. I'd take things I don't use too often to my old bedroom at my parents house (mostly empty) or simply put the things I use daily inside of a closet at my house.

After storing (or hiding) certain things—even for short periods of time—you can truly feel how essential they are to the life you enjoy living, and experience alternative ways of living without them.

Most of us have a table. But we rarely eat on the floor.

FEBRUARY 10, 2020

Let say you stage all your Git changes and then commit them.

git add --all
git commit -m "Edit REDME.md"

There's a typo on REDME — should read README — and we want to "amend" this error.

git commit --amend

The commit --amend command lets you edit the commit message in the vim editor.

You can also change the message by specifying the new message in the command line with the -m argument.

git commit --amend -m "Edit README.md"

As the commit message is part of the commit itself, editing the message alters the commit hash, which means that if you've already pushed a commit to a remote, the remote won't let you push the new edit directly. But you can force that to happen.

git push --force branch-name

FEBRUARY 6, 2020

A year of transformation

We're more virtually connected than ever before. But we're also more disconnected than any other civilization before us. We've created shallow ways of communication (say, email or instant messages) which generate a false sense of connection. It's harder to connect in deep ways with our closest friends—a brief walk, talking on the phone, or a video conference may suffice. But, surprisingly, we spend a huge amount of time learning about random details from the trendiest influencers that we don't even know from our closest friends and probably should.

Today, I share with you what I've learned and what's changed over the past year, and new habits that seem to be here to stick with me for years to come.


Listen to "A Year of Transformation"

FEBRUARY 6, 2020

npx and create-react-app make it easy to create a new app running React and TypeScript.

npx create-react-app my-app --template typescript

Then you go into the folder and run the app.

cd my-app
npm start

You can create a JavaScript (non-TypeScript) app by removing the last bit—--template typescript. And you can also run the app with yarn start.

If, as I was, you're not getting the app working, you might have an older global installation of create-react-app. In my case I installed it with npm install -g create-react-app (which I could verify by running create-react-app -V on the Terminal. To make sure npx uses the latest version of create-react-app you need to uninstall the global version installed with npm.

npm uninstall -g create-react-app

Before you go

If you found this useful, you might want to join my mailing lists; or take a look at other posts about code, React, and TypeScript.

FEBRUARY 5, 2020

git push origin $(git branch | grep \* | cut -d ' ' -f2)

FEBRUARY 5, 2020

"How does one achieve peace of mind?" On the latter point, Plutarch's advice was the same as Seneca's: focus on what is present in front of you, and pay full attention to it.

—Sarah Bakewell, How to Live: A Life of Montaigne in One Question and Twenty Attempts at An Answer

FEBRUARY 4, 2020

The Feed is a casual way to endlessly scroll through your highlights. Think of it as a replacement for twitter or facebook, except you're scrolling through your books, articles, and ideas rather than digital junk food.

FEBRUARY 4, 2020

Ways of talking

It's not I don't have the time but This is not important enough for me.

It's not I can't do this but I didn't sit down to try.

It's not I wish I could do that but I've never tried to do that.

FEBRUARY 4, 2020

There's a full list of colors in Windows C# .NET Framework to be used with WPF and XAML components, both accessible through System.Windows.Media.Colors and System.Drawing.KnownColor. These are their names.

AliceBlue, AntiqueWhite, Aqua, Aquamarine, Azure, Beige, Bisque, Black, BlanchedAlmond, Blue, BlueViolet, Brown, BurlyWood, CadetBlue, Chartreuse, Chocolate, Coral, CornflowerBlue, Cornsilk, Crimson, Cyan, DarkBlue, DarkCyan, DarkGoldenrod, DarkGray, DarkGreen, DarkKhaki, DarkMagenta, DarkOliveGreen, DarkOrange, DarkOrchid, DarkRed, DarkSalmon, DarkSeaGreen, DarkSlateBlue, DarkSlateGray, DarkTurquoise, DarkViolet, DeepPink, DeepSkyBlue, DimGray, DodgerBlue, Firebrick, FloralWhite, ForestGreen, Fuchsia, Gainsboro, GhostWhite, Gold, Goldenrod, Gray, Green, GreenYellow, Honeydew, HotPink, IndianRed, Indigo, Ivory, Khaki, Lavender, LavenderBlush, LawnGreen, LemonChiffon, LightBlue, LightCoral, LightCyan, LightGoldenrodYellow, LightGray, LightGreen, LightPink, LightSalmon, LightSeaGreen, LightSkyBlue, LightSlateGray, LightSteelBlue, LightYellow, Lime, LimeGreen, Linen, Magenta, Maroon, MediumAquamarine, MediumBlue, MediumOrchid, MediumPurple, MediumSeaGreen, MediumSlateBlue, MediumSpringGreen, MediumTurquoise, MediumVioletRed, MidnightBlue, MintCream, MistyRose, Moccasin, NavajoWhite, Navy, OldLace, Olive, OliveDrab, Orange, OrangeRed, Orchid, PaleGoldenrod, PaleGreen, PaleTurquoise, PaleVioletRed, PapayaWhip, PeachPuff, Peru, Pink, Plum, PowderBlue, Purple, Red, RosyBrown, RoyalBlue, SaddleBrown, Salmon, SandyBrown, SeaGreen, SeaShell, Sienna, Silver, SkyBlue, SlateBlue, SlateGray, Snow, SpringGreen, SteelBlue, Tan, Teal, Thistle, Tomato, Turquoise, Violet, Wheat, White, WhiteSmoke, Yellow, YellowGreen

And here's a function that returns a string list—List<string>—with all color names as strings.

/// <summary>
/// Get a list of all Windows colors
/// </summary>
/// <returns></returns>
public static List<string> Colors()
{
    // Create empty list
    List<string> colorList = new List<string>();

    // Get type of KnownColor enum
    var color = typeof(System.Drawing.KnownColor);

    // Enumerate all known color names in enum
    var colors = Enum.GetValues(color);

    // Remove 27 from beginning
    var from = 27;

    // Remove 7 elements from the end
    var to = colors.Length - 7;

    // Only keep color names and not user interface colors
    for (int i = from; i < to; i++)
    {
        colorList.Add(colors.GetValue(i).ToString());
    }

    // Return filtered color list
    return colorList;
}

You can then use one of the colors by its string name.

// Use 19th color
// System.Windows.Media.ColorConverter
var color = ColorConverter.ConvertFromString(colors[19]);

Having the entire list is useful to randomly select colors or to iterate through them. If you have an index and you want to use this list (or a shorter list) and start again when you run out of colors, you can do this.

// System.Windows.Media.ColorConverter
var color = ColorConverter.ConvertFromString(colors[index % colors.Count]);

You could also use a color with its string name, directly.

// System.Windows.Media.ColorConverter
var color = ColorConverter.ConvertFromString("Crimson");

And, lastly, you can cherry-pick and tailor your own custom Color list and use the same calls as before.

public static List<string> colors = new List<string>() {
    "Crimson",
    "MediumSeaGreen",
    "CornflowerBlue",
    "Peru",
    "Coral",
    "SlateGray",
    "Firebrick",
    "Sienna",
    "Teal",
    "Orange",
    "OrangeRed",
};

Before you go

If you found this useful, you might want to join my mailing lists; or take a look at other posts about code, C#, TypeScript, and React.

FEBRUARY 3, 2020

Google Dataset Search is a search engine from Google that helps researchers locate online data that is freely available for use. The company launched the service on September 5, 2018, and stated that the product was targeted at scientists and data journalists.

The site contains 25 million publicly available datasets1 (including data tables, images, video, audio, and more), even though many of them are information pages about existing datasets that can't be directly accessed electronically. For instance, Plans of Sydney Opera House only displays archive information and not the actual dataset—This series is held at Western Sydney Records Centre—but many others, like the architectural drawings and photographs of a Kipahulu real estate house in Maui, Hawaii, can be downloaded (in this case as a PDF).

This is promising.

Want to see older publications? Visit the archive.

Listen to Getting Simple .