Orbital Mechanics, Part 1

Quick note: I wrote this on April 1, posted it two weeks later, but it’s not quite finished. I hope to finish it later, but I didn’t want to leave it sitting too long.

Julian Date

Astronomers are a special bunch. They decided they needed their own calendar, and that the appropriate way to count time was the number of days since 1 January 4713 BCE, or 24 November 4714 BCE depending on which calendar you were counting from. It does solve that issue, which is why some historians have adopted it since.

Oh, and these days are counted starting at noon at the Greenwich meridian: fractional values are the amount of time since the previous date began divided by 24. In other words, midnight of 1 January 2000 CE was 2451544.5. In England. This made a lot of sense in 1583, since astronomers did their work at night, and it would be annoying if your Julian day number rolled over at midnight. That way they could just keep track of the time and have some underling write the same number in front of all their notations the following day.

Now since astronomy happens at all times of the day in all parts of the world at all parts of the electromagnetic spectrum, with still other astronomy happening with gravitational wave detectors and neutrino detectors, it’s fortunate that we have computers to keep track of time. But the Julian day number is still useful!

One simple way is that, by subtracting one day from another, regardless of the cultural calendar in use, you will get an accurate count of the number of days between dates. Another is the aforementioned difference of cultural calendars: proleptic Gregorian, proleptic Julian, Islamic, Jewish, etc.

But how do you get from here to there? I know that today, as I’m writing this, it’s the afternoon of April Fool’s Day of 2019, and that I’m 5 hours behind UTC. But how can I figure out That the Julian date is 2458575 point something?

Let’s start with what we know: Year=2019, Month=4, Day=1. That’s close enough for now, we’ll get in the day fraction later.

Wikipedia gives the following for calculating the day number:

(1461 × (Y + 4800 + (M − 14)/12))/4 + (367 × (M − 2 − 12 × ((M − 14)/12)))/12 − (3 × ((Y + 4900 + (M – 14)/12)/100))/4 + D − 32075

where all division is integer division (not floor divisionvery important distinction that I missed the first…dozen or so times I tried this). Throw away the remainders.

(M-14)/12 shows up a lot. Basically, if it’s a January or February, it’s -1, otherwise it’s 0. Since it’s April, let’s do the appropriate thing with those terms:

(1461 × (Y + 4800))/4 + (367 × (M − 2))/12 − (3 × ((Y + 4900)/100))/4 + D − 32075

Much cleaner! I’ll throw in 4 for the remaining M and 2019 for the Ys, and of course 1 for the D, then it’s just the maths!:

(1461 × (2019 + 4800))/4 + (367 × (4 − 2))/12 − (3 × ((2019 + 4900)/100))/4 + 1 − 32075
= (1461 × 6819)/4 + (367 × 2)/12 − (3 × (6919/100))/4 + 1 − 32075
= (1461 × 6819)/4 + 734/12 − (3 × 69)/4 − 32074
= 9962559/4 + 734/12 − 207/4 − 32074
= 2490639 + 61 − 51 − 32074
= 2458575

And we’re there!

It’s a few minutes after 3, so let’s call it 15:10:05.0025 just because. So the fractional day is

(H + 5 − 12)/24 + m/1440 + S/86400
= 8/24 + 10/1440 + 5.0025/86400
= 0.34033567708333333

So the Julian date for “right now” is

2458575 + 0.34033567708333333
= 2458575.34033567708333333.

I’m not nearly ambitious enough to try to turn a WordPress post into one that dynamically changes all the math depending on what day it is (though it can be done, I’ll leave that as an exercise for the reader).

Sidereal Time

Another thing those crazy astronomers decided to do was make up their own clock. 24 hours works great for day-to-day life, but they noticed that the Earth turns once every 23 hours, 56 minutes, and about 4.1 seconds. So why not make a new system of time to pretend 23 hours, 56 minutes, 4.0905 seconds was actually 24 hours?

Why in the world would this be useful?

Well, let’s say you pointed your telescope at a particularly interesting star, and you knew the sidereal time, along with which direction you were pointing your telescope and how high above the horizon it was. If you give your buddy the sidereal time, if he can match your latitude, he can point his telescope the exact same direction at the exact same sidereal time and see the exact same star.

Of course, why would you bother using 1 January as your baseline for this new clock? Of course you’re going to set 0 hours to be equivalent to the moment of the Spring Equinox.

But hey, it’s still a useful tool, so let’s see how you calculate it.

First, we need the Earth Rotation Angle.

2π(0.7790572732640 + 1.00273781191135448(tU − 2451545)) where tU is our old friend the Julian date. This is in radians, so can be converted to degrees, minutes, seconds in the usual way. For our example time from earlier, this works out to 7050.367142462069. Normalizing to 2π radians per circle this is 0.633227806573089, which works out to 36°16’52.61″, or 2:25:07.51.

This has to be tweaked based on one’s longitude (positive to the east), precession, and nutation, with longitude making by far the largest contribution.

Square Roots

Don’t ask—these posts don’t (yet) have any thread connecting them. Maybe one day I’ll get there.

So I was trying to figure out the square root of 10005, and trying to be a bit more accurate than “slightly over 100”. Problem is, the algorithm I learned seems to be, let’s say, unwieldy, or not quite how I remembered it, when the initial number has lots of zeroes in it. Turns out there’s a slightly easier solution, at least in terms of how many steps you have to remember, and how complicated the math can begin.

Step 1, guess. Your guess doesn’t matter a whole lot, but your guess can’t be zero. 100 is a great guess for 10005.

Step 2, divide the initial number by your guess. 100.05 in this case

Step 3, take the average of your guess and the result of step 2. This is your new guess. 100.025 in this case. Repeat steps 2 and 3 until you’re satisfied with the accuracy of your result.

How accurate does the next iteration get in this particular case, though?

10005/100.025=400200/4001=100+100/4001=100.02499375156210947263184203949… (the first 500 decimal places repeat themselves). Then, average this number with 100.025 for our next approximation: 32016001/320080=100.02499687578105473631592101974…

Considering our initial guess of 100 is 0.02% off of reality, differing by less than 0.025, it doesn’t take much to get even more accurate.

Here’s a table, adding a different guess of 1, rather than 100, to show how this method converges:

IterationGuessAccuracyGuessAccuracy
01003-nines1not good
1100.0257-nines5003actually worse
2100.02499…15-nines2502.49990…slightly better, but still very bad
3100.02499…30-nines1253.24895…moving in the right direction
4100.02499…62-nines630.61610…closer
5100.02499…124-nines323.24077…and closer
6177.09646…almost there…
7116.79555…almost there…
8101.22903…huzzah! 98% accurate!
9100.03216…4-nines
10100.02499…8-nines

You roughly double the accuracy, percentage-wise, for each iteration, so the better the initial guess, the more quickly you get to a reasonable answer. Though no matter where you start, you’ll eventually get there.

Indices

A database table typically has an index column. Early on in computing, such an index might have been limited to a single byte, but bytes weren’t always 8 bits long, but that might have meant early databases were limited to 128, 256, 512, perhaps 2048 or 4096 records. Once we standardized on a byte length of 8 bits, and once we started storing more and more data in databases, we had 16-bit and then 32-bit numbers for indices. For some reason, most databases still use signed integers for these, limiting the number of unique numbers to 32,768 or 2,147,483,648 records. Now, 2.1 billion is probably more records than most people use, but Google or Facebook deals with databases on that scale all the time. They don’t use these types of database structures, but the scale is important. If you switch to use unsigned integers, you get nearly 4.3 billion numbers. MySQL allows you to specify a signed 64-bit number for an index: 9.2 quintillion. Even for Google or Facebook that’s probably enough. However, there are more possibilities. An unsigned 64-bit number is 18.4 quintillion. An unsigned 128-bit number is 340 undecillion. Now, one method of generating unique IDs is simply counting up: 0, 1, 2, … 340 undecillion, etc. There are, however, procedural ways of generating random(ish) 128-bit unique IDs. Though the output is 128-bits long, there are limitations, meaning it’s only got 5.3 undecillion possible combinations. The birthday problem gives a 50% probability of a collision after 2.7 quintillion randomly generated unique IDs.

Exact(ish) numbers:

2.7 quintillion: 2,714,922,669,395,445,311.9212030374141782570788350112707255…

5.3 undecillion: 5,316,911,983,139,663,491,615,228,241,121,378,304

340 undecillion: 340,282,366,920,938,463,463,374,607,431,768,211,456

9.2 quintillion: 9,223,372,036,854,775,808

18.4 quintillion: 18,446,744,073,709,551,616

4.3 billion: 4,294,967,296

Django Tips

I love Django. The web framework, not the jazz guitarist, though he’s not bad, either. Their documentation is a bit lacking in places, mostly in the details, which may be semi-niche edge cases, but I think it’s worth documenting what I’ve found, even if just for myself (as these posts usually are).

Widget Templates

I’ve wanted to tweak a few, and have, previously to what I discovered yesterday, gone deep into the weeds to modify the templates (in django/templates/django/forms/widgets). There are much easier ways! First of all, there’s an invaluable app, django-widget-tweaks, that, even though the code is a tad stale, does enough to be worth its use. Second, if you want to be fancier about things, or if you use other apps that override widgets (like django-markdownx), newer versions of Django need additional settings that are far from clear in the documentation.

First thing, edit your settings.py file. Add FORM_RENDERER='django.forms.renderers.TemplatesSetting' as its own line somewhere in the file. If you do this, and only this, you will find yourself presented with an error page where Django is expecting you to provide templates for everything. Maybe this is what you want, but probably not. To fix this behavior, in INSTALLED_APPS, add ‘django.forms’, and make sure this is the last line of the installed apps, or at the very least, after anything that might feasibly override a widget. That’ll take care of details that you don’t feel like worrying about as you develop your app. You might reach a point where you’ve covered every widget with your own, but it’s good to have a fallback just in case one was missed!

ModelForms

So you’re useing ModelForms to help build forms that you don’t have the time or inclination to write get and put methods all the time. Great! That’s what they’re there for! But there are some things that aren’t obvious, by any stretch!

How about passing data to one of these forms via the URL?

Let’s consider the polls model from the tutorial. Say that, instead of adding answers when editing the question (which, yes, in that case, makes more sense, but go with me for a minute) we want to add answers to a question on a page with the url ‘polls/<int:question_id>/add_answer/’. We know we’re adding an answer, and because of the URL we know the question ID, but the normal ModelForm for the given Answer model will ask you to provide the question_id, because of the ForeignKey field.

Here’s what you need to do:

class AnswerAdd(generic.CreateView):
    model=Answer
    def get_form(self):
        self.question=get_object_or_404(Question,id=self.kwargs['question_id'])
        partial_ans=Answer(question=self.question)
        kwargs=self.get_form_kwargs()
        kwargs['instance']=partial_ans
        form=AnswerForm(**kwargs)
        return form

First, you can’t get away without creating an AnswerForm class, but since this only requires a couple of extra lines from what you’d need in your view, and you’d have to duplicate that in your create and update views anyway, it’s probably worth it.

Second, and annoyingly, you can’t instantiate the form by doing AnswerForm(self.get_form_kwargs(), instance=partial_ans), but this is for good reason: because there’d then be two instance keyword arguments in the constructor—not allowed. Thus the separate lines for kwargs. This also allows you to pass in pass in extra data to the form.

Why can’t we do this in get_context_data? Because that method doesn’t handle the object instance.

There is a downside here, too: you can’t use the mere existence of the object in your template to figure out if someone is adding or editing an object. There’s a simple fix, though, just update your template to use this logic instead:

{% if not object.pk %}Create{% else %}Update{% endif %}

Updating Widgets at Runtime

This may be controversial, but I don’t know why. I think it has it place, and it’s situational. I have a number field. It has a meaning, and as the software developer I know what it means, but since that meaning can vary between instances in a rather complicated way that doesn’t lend itself to creating more objects and tables, and since I want to convey that meaning to my users, I want to replace the <input> widget with a <select> widget, a drop-down that’s far more intuitive for my users.

Here’s how you do that, though:

class MyModelForm(forms.ModelForm):
    class Meta:
        model=MyModel
        fields=[
            'field1',
            'field2',
            # you get the idea
        ]
    def __init__(self,*args,**kwargs):
        obj=kwargs.pop('some_object')
        super().__init__(*args,**kwargs)
        self.fields['field1'].widget=forms.Select(
            choices=obj.get_choices()
        )

Removing Widgets Dynamically

This is answered a few places at SO, but it’s worth rehashing here for my own benefit. Sometimes, you want/need to have a field that is only displayed during the creation of an object, or only when an object is updated, but you’re lazy and don’t want to make a CreateForm and an UpdateForm. I’m with you, all the way! And, as usual, there’s a way to do this:

class MyModelForm(forms.ModelForm):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        if not self.instance:
            self.fields.pop('special_field1')
        else:
            self.fields.pop('special_field2')

With the logic above, special_field1 is removed when creating a new MyModel, and special_field2 is removed when updating that MyModel. The downside is that this won’t work in conjunction with passing data via the URL, because you have an instance, even if it’s mostly empty. You have to be a teensy bit cleverer (though I gave this answer out earlier in this post, I only figured it out here, so I’m repeating it for everyone’s benefit):

class MyModelForm(forms.ModelForm):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        if not self.instance.pk:
            self.fields.pop('special_field1')
        else:
            self.fields.pop('special_field2')

Note that this time I’m checking for a value of instance.pk that isn’t a Boolean false. While you create an instance, no primary key is (typically) created until the object is saved in the database. Even if you have some situation where the PK is filled out in the instance you pass to the form, it’s likely there will be something that you can use to test if the form should be an edit or an update.

Deploying Python Scripts

I write a lot of little Python scripts for work, and a few for personal use. Most of them, even the work-related ones, never leave my own machine, because I write them to make my own life easier, and the syntax is specific, confusing, or I am too lazy to put in any error checking and don’t want to have to deal with the consequences of someone else messing something up by using one of my scripts. But for those that are extremely useful, I need to get them in a format usable by the masses.

We’ll use an example of munger.py—your day-to-day involves munging a file for a particular reason—and you want to simplify the process for you and your colleagues. And the function you want to run, because again you were lazy and not terribly forward-thinking, is called mung (not main).

Python is available on target…

If Python (of the appropriate version) is available on the target machine, you could simply pass along the script as a .py file and be done with it. But you’re nicer than that.

If you’re like me, you have a folder chock-full of random Python scripts. The first thing you’ll have to do is make a folder for the one you want to deploy, and give it an appropriate name. Let’s just do this here:

mung/
|-- mung/
| |-- __init__.py
| `-- munger.py
`-- setup.py

The original script was/is munger.py; the CLI command that will, in the end, be run, will be mung (i.e. mung filename.ext). __init__.py and setup.py are empty files for now. Let’s put some code in there.

Most of the time, I don’t bother with __init__.py, but it can be important when using setuptools, or in creating any package. Most of what you put in here is just imports, though, and here will be no different:

from .mung import *

And now, setup.py:

import setuptools

setuptools.setup(
    name='mung',
    version='1.0',
    packages=setuptools.find_packages(),
    author='<your name here>',
    author_email='<your email here>',
    description='a description',
    entry_points={
        'console_scripts': [
            'mung = mung.mung:mung'
        ],
        'gui_scripts': [
            'mung_gui = mung.mung:mung_gui'
        ],
    },
)

Refer to the documentation here if you plan on deploying your script to PyPI: there are a ton more options and keywords to pass to setup, and most of them will help your project’s use if you want to make it public (e.g. a full test suite, documentation, bug tracking, etc.). If you have a larger package, specific dependencies, a more complicated directory structure, they’re all covered there. But for the basics, what’s above should be more than sufficient.

Keep in mind: you must include name, version, packages, and entry_points (technically, entry_points is not required, but it’ll make documentation and explaining/teaching the use of your script that much simpler later—it’s worth it).

Now you’re ready. With those files saved, in the top mung directory (containing setup.py), and after ensuring you have the latest version of setuptools and wheel, run the following:

python setup.py sdist bdist_wheel

You’ll find the built version of your script in dist/mung-1.0-py3-none-any.whl. The version, and ‘none’ and ‘any’ parts of the filename may be different depending on your build options. But you can pass that one file on to your colleagues, and have them run the following to install it:

pip install mung-1.0-py3-none-any.whl

Rename as you feel appropriate before passing it on!

Your built script will be a bit larger, but not by a lot; I used a 1064 byte test file on my own machine as an example and the built wheel was just 2052 bytes!

Python not available on target…

If Python is not available on the target machine, things are a bit easier and a bit harder at the same time. I recommend is getting your hands on the latest versions of PyInstaller (which does not actually create or install things) and NSIS (which does). I’ll only discuss utilizing these tools. If you want to cross-compile, this will not do the job. For that I’d recommend trying to get Python installed on the target computer—it’s probably easier in the long run.

Each of the following options have their pros and cons. If speed is an issue, and rewriting the program in C or installing Python on the target are not options, go with option 1. If portability is the main factor, go with option 2. If you’re tight on file size, try 2a.

Option 1: Installer

Using PyInstaller, building the script into an executable is fairly straightforward, although you don’t have the same flexibility as the previous method. You can’t define entry points, so you need to be able to directly run the script—no function calling after-the-fact. Add something like this to the bottom of your file if necessary:

if __name__=='__main__':
    mung()

Run the following command:

pyinstaller munger.py

You’ll wind up with munger.exe and a bazillion other files in a dist directory. You may have to mess with the spec file that’s created to make it work just right; see the documentation for details there.

With my 1064 byte test input, I wound up with 52 files in the output totaling 12,513,606 bytes.

How do we deploy 52 files? NSIS. Create mung.nsi with the following contents:

!include "MUI.nsh"
#define compression method
SetCompressor /SOLID LZMA

!define MajorVersion 1
!define MinorVersion 0
!define PatchVersion 0

#define version information
VIAddVersionKey "ProductName" "Munger"
VIAddVersionKey "CompanyName" "<Your Company Here>"
VIAddVersionKey "LegalCopyright" "©20XX All rights reserved."
VIAddVersionKey "FileVersion" "${MajorVersion}.${MinorVersion}.${PatchVersion}.0"
VIAddVersionKey "ProductVersion" "${MajorVersion}.${MinorVersion}.${PatchVersion}.0"
VIAddVersionKey "FileDescription" "<Executable Description Here>"
VIProductVersion "${MajorVersion}.${MinorVersion}.${PatchVersion}.0"
VIFileVersion "${MajorVersion}.${MinorVersion}.${PatchVersion}.0"

RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on)

!include LogicLib.nsh

Function .onInit
UserInfo::GetAccountType
pop $0
${If} $0 != "admin" ;Require admin rights on NT4+
    MessageBox mb_iconstop "Administrator rights required!"
    SetErrorLevel 740 ;ERROR_ELEVATION_REQUIRED
    Quit
${EndIf}
FunctionEnd

#define output file
!ifndef LabelVersion
  Outfile "munger-${MajorVersion}.${MinorVersion}.${PatchVersion}.exe"
!endif
!ifdef LabelVersion
  Outfile "munger-${MajorVersion}.${MinorVersion}.${PatchVersion}-${LabelVersion}.exe"
!endif

#define installation directory
# should be C:\Program Files\Munger
InstallDir "$PROGRAMFILES64\Munger" #Insert appropriate directory here

#define installer name
Caption "Munger"
Name "Munger"

#define variables
!define MUI_ICON "myicon.ico"
ShowInstDetails show

!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

#Include logic functions
!include LogicLib.nsh

#default section
Section
  #define options
  SetShellVarContext current
  SetOverwrite ifnewer
  SetOutPath $INSTDIR
  #install file
  File /r dist\*
  CreateShortcut "$DESKTOP\munger.lnk" "$INSTDIR\munger.exe"
  WriteUninstaller "$INSTDIR\uninstaller.exe"
SectionEnd

Section "Uninstall"
  Delete "$INSTDIR\uninstaller.exe"
  !include /CHARSET=UTF8 "remfiles.nsh"
  RMDir "$INSTDIR"
  Delete "$DESKTOP\munger.lnk"
SectionEnd

!insertmacro MUI_LANGUAGE "English"

Add nsis_uninstall_helper.py with the following contents:

import os
import sys

#generate removal file for NSIS
print(sys.argv[1])
with open('remfiles.nsh','w') as fp:
    for root,dirs,files in os.walk(sys.argv[1],False):
        for f in files:
            t=fp.write('  Delete "$INSTDIR\\{}"\n'.format(os.path.join(root,f)[len(sys.argv[1])+1:]))
        for d in dirs:
            t=fp.write('  RMDir "$INSTDIR\\{}"\n'.format(os.path.join(root,d)[len(sys.argv[1])+1:]))

Now you should have something like the following:

somedir
|-- build/
| |-- munger/
| |-- Analysis-00.toc
| |-- COLLECT-00.toc
| |-- EXE-00.toc
| |-- PKG-00.toc
| |-- PYZ-00.pyz
| |-- PYZ-00.toc
| |-- base_library.zip
| |-- munger.exe
| |-- munger.exe.manifest
| |-- warn-munger.txt
| `-- xref-password.html
|-- dist/
| |-- munger/
| | |-- ... <--a bunch of stuff
| | `-- munger.exe
|-- munger.py
|-- munger.spec
|-- nsis_uninstall_helper.py
`-- mung.nsi

In the dist directory, run the following:

python nsis_uninstall_helper.py
makensis mung.nsi

If all goes well, you’ll wind up with munger-1.0.0.exe in the directory. My personal sample came in at a svelte 4,443,448 bytes. This you can distribute like any other installer, and, provided the target user has the appropriate rights, they shouldn’t have much trouble.

Option 2: Single File

Just like in the previous section, when using PyInstaller, building the script into an executable is fairly straightforward, although you don’t have the same flexibility as the previous method. You can’t define entry points, so you need to be able to directly run the script—no function calling after-the-fact. Add something like this to the bottom of your file if necessary:

if __name__=='__main__':
    mung()

Run the following command:

pyinstaller -F munger.py

You’ll wind up with munger.exe in a dist directory. You may have to mess with the spec file that’s created to make it work just right; see the documentation for details there. But that’s all you need! Pass along the file as-is, and you shouldn’t have too many issues.

With my 1064 byte test input, I wound up with just the one file totaling 6,094,767 bytes. Not too shabby!

Option 2a: Single File (With UPX)

You can, perhaps, compress your file even more using UPX. I won’t go into installing or configuring it, see the documentation for the details, but here are my results:

Run the following command:

pyinstaller -F --upx-dir=path\to\upx munger.py

You’ll wind up with munger.exe in a dist directory. You may have to mess with the spec file that’s created to make it work just right; see the documentation for details there. But that’s all you need! Pass along the file as-is, and you shouldn’t have too many issues.

Again, with my 1064 byte test input, I wound up with just the one file totaling 5,057,013 bytes!

New Kilogram!

What news! There’s a new kilogram on the block! Le Grande K is being replaced by defining Planck’s constant to \(\Large{h=6.626\ 070\ 15\times10^{-34}{\rm J\ s}}\). The kilogram is hiding in the “J”, the joule, which is a compound unit \(\Large{{\rm kg}\frac{{\rm m}^2}{{\rm s}^2}}\). It isn’t official until May 2019, but it nails down another universal constant!

It’s perhaps less exciting, but just as important, that other constants are also being defined. The highlighted rows are the new definitions:

ConstantValue
\(\Large{\Delta v_{\rm Cs}}\) \(\Large{9\ 192\ 631\ 770{\rm Hz}}\)
\(\Large{c}\) \(\Large{299\ 792\ 458\frac{\rm m}{\rm s}}\)
\(\Large{h}\) \(\Large{6.626\ 070\ 15\times10^{-34}{\rm J\ s}}\)
\(\Large{e}\) \(\Large{1.602\ 176\ 634\times10^{-19}{\rm C}}\)
\(\Large{k}\) \(\Large{1.380\ 649\times10^{-23}\frac{\rm J}{\rm K}}\)
\(\Large{N_A}\) \(\Large{6.022\ 140\ 76\times10^{23}\frac{1}{\rm mol}}\)
\(\Large{K_{cd}}\) \(\Large{683\frac{\rm lm}{\rm W}}\)

This allows the definition of the seven SI units to universal constants.

Unit Definition
second (s) \(\Large{\frac{1}{\Delta\nu_{Cs}}}\)
meter (m) \(\Large{\frac{c}{\Delta\nu_{Cs}}}\)
kilogram (kg) \(\Large{\frac{c^2}{h\cdot\Delta\nu_{Cs}}}\)
ampere (A) \(\Large{\frac{1}{e\cdot\Delta\nu_{Cs}}}\)
kelvin (K) \(\Large{\frac{k}{h\Delta\nu_{Cs}}}\)
mole (mol) \(\Large{N_A}\)
candela (cd) \(\Large{\frac{1}{h\cdot\Delta\nu_{Cs}^2\cdot K_{cd}}}\)

The compound units used in the definitions of the constants are a shorthand.

Another aspect that is not getting much press is the downside of defining the kilogram and Avogadro’s number: 1 mole of 12C no longer has an exact mass of 0.012 kg. Now the mass of 12C is \(\Large{0.0120000000(45)\frac{kg}{mol}}\). Perhaps in the future these definitions can be reintegrated. Technically, they are still related by \(\Large{N_A=\frac{\alpha^2M({\rm e}^-)c}{2R_\infty h}}\), but we aren’t exactly certain about the values of \(\Large{\alpha}\), \(\Large{M({\rm e}}\), or \(\Large{R_\infty}\), so there’s still work to be done! Avogadro’s number may not move, but we may figure out these guys yet!

While these changes are official, they don’t become “the definition” until 20 May 2019, so you’ve still got some time to adjust your voltmeter by 0.00001% or so.

A tous les temps, à tous les peuples.

Style

Web presentation is balled up in Cascading Style Sheets (CSS), but there are additional tools that may be useful to those starting out, or re-learning the art of web development.

There are several critics of CSS preprocessors, and they have their points, but I’ll probably continue to use them. Here are the big ones, their pros and cons, and some options if you wish to write in plain CSS.

All of the below have some things in common:

  • Variables
  • Conditionals
  • Nesting
  • Plugins/Mixins
  • Inheritance
  • Functions
  • Math
  • A vanilla CSS file will pass nearly unaltered through any of these.

CSS Crush

CSS Crush, for the most part, is vanilla CSS with automatic generation of vendor prefixes.

Stylus

Stylus modifies the syntax by eliminating the need for braces and semicolons. You can include them if you like, but they are optional.

Less

Less, through less.js, allows its use in the browser without running it through a preproccessor, though for production this is discouraged.

Sass

Sass comes with two syntaxes, making it perhaps more flexible for writing than the others, provided you utilize the appropriate extension in your file. SCSS uses CSS syntax, and Sass eliminates the braces and semicolons.

So why would you pick any of these? They primarily add a step to deployment of your web page, and that’s about it, right?

It used to be that none of the features mentioned had much, if any, support within the CSS spec or browsers. CSS3, and most browsers, support CSS variables now. Conditionals for their primary use-case exist via @supports and @media. Math is also well-supported with calc, unless you’re trying to do something really fancy (and you can even mix units and percentages, which can’t be done with a preprocessor!).

It should be noted, especially in relation to CSS Crush, that Android, Chrome, iOS, Firefox for iOS, Safari, and newer versions of Opera all use the “-webkit-” browser prefix (Chrome, since v28, uses the Blink rendering engine, but this is a fork of WebKit). Desktop versions of Firefox still use “-moz-“. Internet Explorer and Microsoft Edge still use “-ms-“. But common practice now is for browser makers to hide these experimental features behind user-controlled flags/preferences which can help fast-track their production implementation in ridiculous version release schedules (every six weeks for Chrome and Opera, six-to-eight for Firefox. WebKit prefixes can still be useful, as many, if not most, of these eventually get standardized. So basically, if you use any browser prefix at all, “-webkit-” will allow you to cover between 67% and 73% of the desktop market and 94% to nearly 100% of the mobile market.

Variables in vanilla CSS require five extra characters to reference, and typing “var()” might seem tedious to you.

:root {
  --primary-color: #4042c8; /* pretend this is carefully chosen rather than totally random */
}

.colorful > p {
  color: var(--primary-color);
}

Nesting is perhaps not the most elegant, solution, and is arguably less maintainable, than specificity or defining classes for everything.

Lastly, while vanilla CSS files may come out of preprocessors relatively unscathed, those that use features of them may produce CSS files that are somewhat larger than expected.

____Script

You’ve probably heard of JavaScript. You may have heard of TypeScript, ECMAScript, JScript, VBScript, LiveScript, CoffeeScript, and ActionScript, and might wonder what any of them have to do with each other, or with Java (as a beverage, island, or computer language).

Essentially, JavaScript and Java appeared at roughly the same time, in 1995, had similar syntax, and JavaScript followed Java’s naming conventions, but that’s pretty much it. It’s possible, perhaps even probable, that JavaScript took its name to capitalize on the popularity of the nascent Java.

Mocha was the development codename of the language, LiveScript was its name when in beta, but it was renamed JavaScript when announced in December 1995 and released with Netscape Navigator 2.0.

TypeScript is a superset of JavaScript developed by Microsoft in 2012. Any valid JavaScript code is valid TypeScript code, but not every valid TypeScript code is valid JavaScript code. Typescript compiles to plain JavaScript.

CoffeeScript is an alternate syntax for JavaScript designed to be more readable. It compiles to plain JavaScript.

ECMAScript is the specification created to standardize JavaScript. The committee that develops these standards is Technical Committee 39 (TC39) of Ecma International, standardized in ECMA-262 and ISO/IEC 16262. While originally the European Computer manufacturer’s Association, the name of the Switzerland-based organization is no longer considered an acronym, but the specification retains it for historical reasons. The name is a compromise between the organizations involved: Sun Microsystems, Netscape, and Microsoft. Since 2015, there have been annual releases of ECMAScript syntax.

As an aside, here are a few other Ecma International standards you probably know but didn’t know who came up with them:

  • 7-bit coded character set
  • FAT12/FAT16 file system
  • CD-ROM volume and filestructure
  • Universal Disk Format
  • C# language specification
  • Eiffel language specification
  • Office Open XML
  • JSON
  • Dart language specification

As ECMAScript is a specification, JavaScript is a subset of ECMAScript. JScript and ActionScript are also subsets. JScript was created for Microsoft’s Active Scripting engine, so it can be used with Internet Explorer, Active Server Pages, and Windows Script Host, along with VBScript (Visual Basic Script) and PerlScript. It is essentially the same as JavaScript with a few additions specific to Microsoft, but a different name was chosen to avoid trademark disputes with Sun Microsystems. ActionScript was created by Macromedia for use with their Flash product and lives on today in Adobe AIR.

Due to the editor-level debugging available through the use of TypeScript, I plan to use it and its enforced typing in tutorials here.

CSS (Step 2: Flexbox)

With the basics and terminology out of the way, we come to layout. I barely touched it last time—all we had was some articles and boring old vertical scroll. Yeah, we did some fancy things, but nothing groundbreaking, or even that interesting.

Today, we’re going to tackle flexbox. Like all of these, this isn’t going to be a comprehensive tutorial, but if you’re reading this, it’s probably at least as new to you as it is to me.

First off, you might be happy to know that flexbox can make vertical centering not only possible, but simple! And it’s not the only solution on that front, but we’ll get there eventually.

You want columns? Easy peasy! You want them to resize proportionally depending on the viewport? No problem! You want them to stay the same size regardless? Still simple! Reorder those columns depending on viewport or media or because it’s Tuesday? Done. You want a different number of columns depending on viewport? Do you want to make sure the space between the columns is even regardless of the column’s size, or make sure the center of the columns are evenly spaced, or there’s an even amount of space between the columns? Do you want to vertically stretch columns so you don’t have a ragged bottom? Would you prefer them all with the same centerline? How about a ragged top and aligned at the bottom? Swap out columns and rows in the above and you’re still set, all with one new tool in your box!

This probably sounds too good to be true, but I promise, it works. It’s not the be-all, end-all for layout, and this won’t cover some designs, but it’s pretty…flexible (I think when writing about flexbox that joke is compulsory)! And you might wonder about browser support, or be worried about a zillion polyfills cluttering your code. Fret not! All real browsers support it, and have for years. IE 11 technically supports it, but it’s buggy.

This time we’re going to change things up. Instead of a blog-like page, let’s build a user testimonials page for a business, Spacely’s Space Sprockets. How, exactly, are they better than Cogswell’s Cogs?

We have to put our testimonial blocks in a container, first, and set that container to display:flex. But if we leave it like that, all the nested divs end up in one horizontal line. Sometimes that’s appropriate, but not typically, and not here.

Now we get on to the magic.

flex-direction tells the browser how to order the boxes. Still in the “container” class of the CSS, play around with the following:

flex-direction:row;
flex-direction:row-reverse;
flex-direction:column;
flex-direction:column-reverse;

row will have no (additional) effect, because that’s the default once you have the container set to display:flex. row-reverse might confuse you a bit—it does reverse the order of the contained images, but it does this by stacking them from right to left in your viewport. Your browser may not recognize that you may need to scroll left to see some of the nested elements. column will be what you saw before adding display:flex, and column-reverse will be a similar column, but with the opposite order.

What we really want is to wrap these testimonial blocks. flex-wrap to the rescue!

flex-wrap:wrap;
flex-wrap:nowrap;
flex-wrap:wrap-reverse;

If you add flex-wrap:wrap, you expect that the boxes will stack up nicely next to each other–but they don’t! The divs appear to have been resized horizontally, but are still stacked in a column. flex-direction won’t help here, because they are, technically, in a row, but wrapped as if each box was a word in a paragraph of text (which by default automatically wraps). If you have a wide enough viewport, or you zoom out, you may be able to get them to line up side-by-side, but we need a solution for this, because instead of fixing the problem, we created a new one!

Before we move on, you can combine the above attributes with the shorthand property flex-flow, e.g. flex-flow row-reverse wrap;.

We can ameliorate the issue by defining a specific width to the item, and that’s what we’ll do for now. Since I chose 300px wide images, let’s set the item (.testimonial) width to 300px.

Take note of how wrap-reverse and row-reverse/column-reverse differ. With wrap-reverse, you keep stacking images from right to left but, in the case of a row, when you get to the end (left), you shift the entire row down and begin a new row on top (instead of moving your stacking down a row.

Notice, since I have 11 testimonials, regardless of your viewport (okay, so long as the boxes line up side-by-side and it actually does wrap, i.e. the width is greater than 600px but less than 3300px), the boxes won’t fill up the entire width. What if we want to avoid that annoying whitespace? Add flex:1; to the testimonials class and notice that, however many items are in a row, they will stretch horizontally to fit. Taft, for instance, has more to say than some of the others, so lets give him some more room. Add

.taft { flex: 2; }

These numbers are proportions, so they do not have units. His testimonial won’t necessarily take up twice as much room as the others. Because his flex-grow property is twice as big as the others, the container will do its best to make his item’s width twice as wide, but may not succeed.

I’m introducing the shorthand property right up front here, because that’s probably what you’ll use most. What we’ve specified above is the flex-grow property, but that also implicitly sets the flex-basis to 0. There’s also a flex-shrink property. That really only works without wrapping, and is essentially the inverse of flex-grow, shrinking items proportionally (as available) to attempt to fit in the viewport. Feel free to turn off wrapping, remove the images, and play around with it, but I won’t include examples here. The default for that is 1, however. Anyway, let’s add a flex-basis of auto to the .testimonials class:

.testimonials {
  //...
  flex: 1 1 auto;
  //...
}

What happened? Taft’s impressive girth has gone away! His flex-basis, as I said, was implicitly set to 0, so what does that mean? It takes a look at the item’s width property (300px), ignores the whitespace, and uses that as its default size before distributing/flexing the item within the container. What the auto keyword does is takes a look at the item’s width property, then takes all the white space, and distributes that among the items proportionally.

Update the .taft class to flex: 2 1 auto;. Now the whitespace width he gets allocated is twice as big as the whitespace width allocated to the other .testimonials, or as close as your browser can get. If you want him to take up all the space, or as much as possible, without messing up the stretchiness of the bottom/wrapped row(s), set the flex-grow property (the first number) to something absurdly large, like 9999. This basically replicates what we had before we included flex-basis.

What if, instead of stretching the boxes, we wanted to put spacing between them? Take out the flex line in the testimonial, and in the container, add justify-content:space-evenly;. The extra whitespace on each line is split and placed in each gap. If there are four items in a row, and 240px of whitespace at the end, this will put 48px before the first item, 48px between the first and second, etc., and 48px after the last item in that row.

justify-content has some other keywords that can be used:

justify-content:space-evenly;
justify-content:flex-start; //this is the default
justify-content:flex-end; //lines up things at the end (right or bottom of most containers)
justify-content:center; //sounds promising...
justify-content:space-between;
justify-content:space-around;

space-between would take that theoretical 240px of whitespace on the end of a four-item line and place 80px between each item, but no whitespace before the first or after the last.

space-around takes that whitespace and divides it into 8 chunks, 24px each, and puts it before and after each item. Which means there ends up being twice as much whitespace between items as there is before the first or after the last.

All of these can be quite useful in certain contexts. For this one, space-between and space-evenly probably look the best.

And if you want to put all the whitespace after a specific element, add

margin-right:auto;

(or margin-left, or margin-top, or margin-bottom, whichever is relevant).

We’re not done yet! Notice that, for each row, the testimonial blocks stretch vertically to perhaps an absurd degree, based on whichever item has the most content. Another property, align-items, is here to help.

align-items: flex-start;
align-items: flex-end;
align-items: center;
align-items: baseline;
align-items: stretch; //default

Go ahead and play with these (in the container); some are more self-explanatory than others. Baseline is, perhaps, the confusing one. It will align all items with the baseline of the first nested element, which, in the example, is the images. This is why Bill Murray and the kitten have different image heights in the example. Play around some more by moving some text above the image, and watch how the result aligns. The bottom (baseline) of the first line of text is the line that’s used for alignment.

How about changing the alignment of just one item? The align-items property may be tempting, but it’s for use in a container. align-self is the one to use here. Add to your CSS file

.seagal { align-self:flex-end; }

and watch what happens. The same properties are available for these as with align-items, with the addition of auto, which is the default, and inherits the align-items property of its parent.

Almost finished. Order is something else that can be changed with flexbox using, oddly enough, the order property.

Say we want to move the zombie to the front. One way is to update the HTML to movie his testimonial up. Another way, if this were a data-driven site, would be to update the query such that the brain-eater was returned first. Or, you can do it using CSS.

Add this to the CSS file:

.zombie { order:-1; }

The default value of the order property is 0, so you’d either have to specify everything else with a higher number, or give the particular class a negative number. Either solution is fine.

One major caveat to using the order property: if a speech reader is being used, for example, this will not change the order content is aurally presented. But in a semantic layout, the content should be presented first if no stylesheet is used, thus, for instance, a navigation bar can be coded last in the HTML yet be presented first in a visual medium.

Try to use what you’ve learned to place text of one of the testimonials above the image. Hint: it involves the order property, the flex-flow property, and the display property.

How about the problem we started with? Perfectly centering an item, horizontally and vertically? Add the following:

.center-container {
	background-color:blue;
	display:flex;
	justify-content:center;
	align-items:center;
	width:95vw;
	height:95vh;
}
.centered {
	background-color:green;
	font-size:3em;
	padding:1em;
}

The highlighted lines are all that’s necessary; the width and height ensure we have a sufficiently large container to demonstrate the concept, and the .centered class adds some styling to the bit of graffiti.

Before I wrap this up, I’m going to address responsive images. I’ll cover them more comprehensively later, but we sometimes will want our images to take up the space they’ve been given  in case, for example, we want them to shrink to make room for Taft.

.testimonial img {
	height:auto;
	width:100%;
}

You’ll also probably want to add a min-width property to the testimonial class so that the images/items don’t shrink too much. Or a max-width if you don’t want Taft to get too big.

Resources & References

Terminology

A quick aside to define some terminology you may run across while browsing CSS Tricks, MDN, A List Apart, and other web-focused sites (I may have even used a couple myself):

polyfill: a “shim” for a browser. A method to emulate future features (like CSS drop caps) on browsers that don’t yet support them, usually using JavaScript.

fallback: if code, images, fonts, or other resources aren’t loaded yet, what you might expect to see on your web page. Sometimes also used for accessibility, things like placeholder text for images.

media query: discovering characteristics of the user environment, and conditionally applying styles based on those characteristics. Width of the viewport is probably the most common, followed by “screen” and “print” to define different styles for a printed page than a display. See here for more.

viewport: the window through which a user is viewing your site. This could be a on a 43″ 4K monitor (like the one I typically use), a 4.7″ 1344×750 iPhone display, or an old CGA dinosaur, but the window, typically the browser, can (typically) be resized further. Out of habit, my browser is often set to a window size of 2560×2120 (40px taken by my OS taskbar), but my viewport size, thanks to the window chrome, is 2550×2000.

responsive: this one means what it says on the tin, but it can help to define it in the context of web design. A design is responsive when, depending on, or regardless of, the viewport size, it looks appropriate. This could involve moving a navigation section to the bottom of a page or collapsing it into a hamburger menu at the top when the viewport is narrower than a certain size, loading higher resolution images for displays that can handle them, and/or being flexible to portrait and landscape viewing modes.

specificity: this one I left for last, because I want to talk about it. Specificity, in CSS, has a very technical meaning. Generically, however, it means how targeted your selector is. Are you targeting an element, a class, an ID? Are you using a pseudo-selector? Are you using “!important” (by the way, don’t do that)? Are you specifying styles inline (by the way, don’t do that either)?

Specificity can be calculated as follows:

a=number of ID selectors

b=number of class selectors, attribute selectors, and pseudo-class selectors

c=number of type selectors and pseudo-element selectors

The specificity is a||b||c, where “||” is the concatenation operator, and the number system has an effectively) infinite base.

h1#test {
  //specificity of 101: an id and a type
  color:red;
}
h1.test, h2.test {
  //specificity of 11: each one is a class and a type
  //because it's lower, h1 will be red and h2 will be blue.
  color:blue;
}
h1, h2, h3 {
  //specificity of 1: each one is a type
  //because it's lower, the h1 will be red, h2 will be blue, and h3 will be green.
  color:green;
}
h1[id=test], h2[id=test] {
  //specificity of 11: each one has an attribute selector, even though it is an ID, and a type
  //the specificity of the first selector wins, so an h1 with an ID of test would be red; but there's nothing specifying just #test, so h2 with that ID would be yellow. But you're not allowed to have two IDs that are the same in a single document, so don't do that! If the h2 had an ID of test and a class of test, it would still be yellow, since this is the last definition with that specificity in the CSS file.
  color:yellow;
}

If you want the dirty details, go here. If you want something a bit more user-friendly, go here.