I take a lot of screenshots. Taking them is an easy thing to do but, if you do a lot of them, processing screenshots can become a time consuming process. For me it usually involves at least this many steps:

  1. Take the screenshot (on a Mac pressing ⌘-shift-4 and dragging the crosshairs over your target will do the trick).
  2. Rename the file to something that makes sense (otherwise it'll be named something like Screen Shot 2016-10-29 at 8.11.27 AM.png
  3. Find the new image file on the desktop and double click it to open in the Preview app.
  4. Use Preview to resize the picture then save the file. On my website I display product images in a way that requires them to be no larger than 150px wide. However, I've been thinking a lot about retina screens lately and I've been starting to collect versions of my images that are twice as large too.
  5. Upload to my server using my FTP client (I use Transmit). This involves navigating about 6 layers deep into my file system.
  6. The point of these screenshots is to display them on my Web site, so the last step is to enter the image name into my database. So, I either have to retype the name I chose for this image or copy and paste it.

Every step is simple. However, when you find yourself repeating a multistep task like this it's time to consider some sort of automation.

The Mac has some great tools for automation. For the super nerdy, bash scripts on the command line, python or ruby scripts (or even php or javascript for that matter) can work wonders. There's also AppleScript, which is supposed to be a layperson's scripting language but, despite all my programming experience, I have a hard time wrapping my head around it.

There's even some absolutely fantastic third party apps like Hazel and Keyboard Maestro. However, a lot of workflow problems like this one can be solved by the simplest automation solution, Automator.

Automator makes automation easy by letting you drag steps into your workflow. These steps are chained together, so each one takes an input (which can be a file, text, or something else) and outputs an, er, an output. Oftentimes this output is the same thing that was input, sometimes it's something different that was created by the step.

Note: To quickly find these actions start typing their names into the search box at the top of the screen. Make sure Library is highlighted in the left column, otherwise you will only be searching a smaller subcategory and you might not find what you're looking for.

 

So, this is the workflow that I ended up with. 

The first step is to take the screenshot. I want this to be interactive so that I'll be able to select the exact part of the screen that I want for my screenshot. The other option is to save it to the clipboard or to a location. I first made a folder on my desktop called eyedock lens image and put an image inside of it named new screenshot.png, then I chose the Other option in the Save To: dropdown and navigated to this image.

One thing that I wanted to point out on here is that the steps you drag into automator are usually chained together, meaning that the output of one step is, by default, the input for the next step. This is indicated be the circle in the image above.

However, sometimes we want to break this chain. This is true here. My second step is to ask for some text that will be a name for this picture, which is a step that does not need an image to be passed into it. So, when I added this step I right-clicked on it and chose the Ignore Input option. As you can see (where I put the red 'X' above) there is no visible connection between the steps.

Asking for text will pot up a little dialog box that will ask for some text. I want this to be mandatory so I checked the Require an answer checkbox.

The output of this step is going to be the text that the user types in, and this will become the input for the next step, which is Set value of Variable. I named my variable Name, so now this variable it will equal whatever text the user entered in the above step.

After setting my variable, I chose the Copy to Clipboard  step. This will put the name of my image file on the clipboard so I can just paste it where I want it. This may not be an important step for everyone but it's a helpful one for me.

The next step is Get the specified finder items. This is going to retrieve the screenshot image file that we took in step one. Because this does not require the text from the above steps I once again chose the "Ignore Input" option - we are starting a new chain here. On the Get the specified finder items step I simply clicked the "add" button and navigated to the location of my image file. The output of this step will be the image file, which we're going to pass on to the next step,

Rename Findere Items: Name Single Item. I'm going to rename the full name of the file, so I selected this option and then I used the variable NameI from our second step and appended the text "_original.png". So, if the user enters the text "myPicture" in step 2 then the file will now be named "myPicture_original.png".

After renaming the file I'm going to set another variable that refers to this file. It's always best to make variable names that make sense, so I called this variable Original Image. 

Then, I duplicate the file. The output from this step will be the duplicated file (not the original), so my next step, Rename Finder Items, will rename this file (otherwise it well be called myPicture_original copy.png). I'm ultimately going to make two copies of this image and this one is going to be twice as big, so I will rename this one with the variable name + "@2x.png". In our example it will be myPicture@2x.png. Lastly, I set this to another variable and, trying to keep things organized, I call it 2xImage.

I'm thinking, at this point, that these steps aren't requiring as much explanation. The "2x" file is duplicated, renamed (this time it will simply be myPicture.png), and stored to another variable (1xImage). In the next step we finally scale the image. For my Web site I place images in a position where I want them to be no larger than 150px, so I select the appropriate options to give that result. This scaling will be done in a way that respects the proportions of the image - it won't turn your image into a 150px x 150px square, it'll just make sure it's not larger than 150px in either dimension.

We created a 2x image, but we haven't scaled it to our desired size yet. So, we're going to get that image and do that now. This is why we assigned a variable to that image earlier - it makes it really easy to retrieve and perform more actions on it. So, our next step is to Get the value of variable "2xImage". Note that I once again selected the "ignore input" option so this step wasn't chained to the ones above it.

Then, we scale the image - I wanted this to be twice as big so I selected 300px this time.

Now, all the images I wanted have been created - the original, the 1x, and the 2x. The last step is to upload them. Unfortunately Automator doesn't have any built in steps to upload files, but any good third party app should provide Automator actions. As I mentioned above I use Transmit and it provides exactly what I need for this step.

So, the next step is to drag in the Upload step and configure it with your server credentials.

After I've uploaded the 2x image, I get the 1x image (via the 1xImage variable) and upload that one too.

 

And that's it!

Now save the app and name it whatever you want - choose something that make sense, like screenshot uploader. You can activate it like you would any other app (by double clicking it). However, if our goal is to increase efficiency, I'd use an app launcher like Spotlight (hit ⌘-space and start typing screenshot uploader, or whatever you named it). I'd also recommend giving your app a custom icon to make it more recognizable (otherwise all your Automator apps will look the same!).

Here it is in action:

Wrap-up

There's about a 97.6% chance that you don't need the exact same thing that I need here. Hopefully you'll find this helpful, though, and take this and customize it for your own needs. Automator is obviously highly customizable, and there's no right or wrong way to solve a problem. In fact, as I typed this up I thought of a couple ways this workflow could be changed to work more efficiently. This is one more way that Automator is like "real" programming: Job one is making something that works, jobs 2 through 99 are refining what you've done - if you're so inclined! Just don't go overboard - it's easy to do, as this xkcd comic sums this up perfectly!

There is one issue I don't like about this workflow. It isn't very smart. If an image is smaller than 300px, or 150px,  it will still try to create images in those sizes. As a consequence a 100px image will be blown up to 150px and 300px and, when you're blowing up images like this, they'll be blurry. This is an issue that could be addressed by writing a script (Applescript or otherwise), but this is beyond the scope of this today's blog post.

One other thing to consider - this script keeps three images on your hard drive (the original, the 1x and the 2x). You may or may not want this. If not, consider customizing it yourself by adding some actions to delete the files after the upload.

Posted
AuthorTodd Zarwell
Tagstech

Well, I'm going to compete in a Crossfit competition in one week! God help me!

My coaches and teammates (PFD Crossfit - check 'em out!)  have been incredibly supportive. In theory, I was a college athlete: I ran track at tiny Ripon College, who's biggest claim to fame is the fact that Han Solo went there. One of the other noteworthy thing about Ripon was that it was the location of the Rippin' Good Cookie factory. Oftentimes long distance runners on the team would run to said factory and bring back a bag full of cookies for the team to snack on after track practice.

So, needless to say, I never developed the best pre-competition dietary rituals so I'm learning as I go. My coach Chris gave me a Word document full concepts like macronutrients and glycogen storage process. I've read through this a few times and I thought I'd share the main points with you here.

 

 

Water is the a critical factor in the glycogen storage process. The body needs water in order to store glycogen in the muscles and the liver. 

 

 

 

Digestion is king. You want to look to foods that are EASILY digested by the body. Digestion takes a lot of energy, and the last thing you want to do when you’re staring a competition in the face is thwart valuable energy to a bodily process like digestion. 

For example, rather than a whole banana or whole yam, use baby food variations of these items in the pre comp/intra comp protocols. Every piece of food that’s consumed first think about how easily it can be digested then transported effectively. 

Or you could do this . . .

 

 

 

Get lots of sleep. The week before the competition start getting 45 minutes more sleep than normal.

Yeah, that's easier said than done...

Posted
AuthorTodd Zarwell

Back in 5th grade I, like a lot of kids, was pretty fascinated with calculators. While I was growing up my dad had an older one with LED numbers that gave me lots of nerdy enjoyment while I multiplied and divided random numbers together. Later, as my math skills progressed, I asked my parents for fancier scientific calculators so I could do trigonometric functions, calculate logarithms, and do things like arbitrarily raise numbers to the 5th power. By the time I was in 7th grade there was rumors that we would be required to buy graphing calculators for that year's math classes. Sadly, it never happened (and I never did get a graphing calculator).

Photomath - Camera Calculator  

Photomath - Camera Calculator

 

So, I can't help but think about what the nerdy 10 year old version of me would think about my calculator options nowadays. Of course, most of us don't carry around standalone calculators, but we all have pretty good ones built into our phones. The iPhone's built in calculator (while in landscape mode) is already better than that scientific calculator from my youth.

However, there are tons of great calculator apps out there that do amazing, out of the box things. I've actually tried very few of them (after all, how many calculators does someone need?). I've liked CalcBot as a small step up from the built in calculator, and PC Calc seems to be widely regarded as one of the best full featured calculator on the app store. Soulver is kind of a cross between a spreadsheet and a calculator that I find really useful for certain tasks.  MyScript Calculator has the amazing ability to interpret mathematical symbols and numbers that you write on the screen with your finger and then solves the problem.

All that being said, the app that really blew my hair back is Photomath. This app lets you type in math problems in a pretty convenient way, which is no small task, because entering formulas with parentheses, exponents, numerators and denominators, etc, can be a cumbersome process.

Even more fun, though, is the fact that you can actually take a picture of a math problem and it will interpret the math symbols and numbers, clean it up, and solve the problem. If there's a variable in the math problem it will intelligently solve for x.

 

The really really cool part, however, is that it this app does what all my teachers reprimanded me for NOT doing when I was in school: It shows its work. If you click on the answer the app will show you a long list of steps that it used to solve the problem. Clicking on a step will give a little explanation of which mathematical principles were used for that step.

 

 

Whenever I see something like this I imagine voices rising up in protest, crying out  "Wait, kids should be doing this on their own, not letting an app do it for them!". In fact, I can see my 10 year old self discovering something like this and, with an evil laugh, saying "This app will be able to do all my homework for me - ahh ha ha ha ha!".  My adult self, however, is of the opinion that this is an awesome way to acquire the fundamentals of math. In my experience one of the best ways to learn is to break down how someone else solves a problem. Unfortunately not every student has access to someone proficient in math, but with an app like this kids (and adults) can have access to a robotic math tutor. Plus, I think this would be a great way to check your math homework and, if you got the answer wrong, figure out where you went wrong.

Could this be abused? Probably. But I think the upside is a lot greater than the downside.

Also, it's worth noting that the app isn't perfect. Knowing it's limitations can be a learning experience too. For example, I scanned this trigonometric problem from one of my optics textbooks:

 

From the white box at the bottom it appeared to be scanning the formula correctly, but the answer it was giving was different than the answer in the book (the yellow arrows in the picture above illustrate this). At first I was puzzled, but then I realized I've run into similar problems when writing optics calculator programs. Programming languages usually accept radians for trigonometric functions, and this textbook problem was using degrees. Sure enough, when I converted the degrees to radians the answer agreed with the textbook. So, lesson learned: Computers are great tools, but you can't blindly trust them. Programs take an input, process it, and return an output accurately, but sometimes they process things differently than you expect them to!

To summarize, I continue to be amazed at what app developers are able to do. This is an impressive app and I think it could be a very useful tool for anyone learning math concepts. We live in such exciting times!

 

Posted
AuthorTodd Zarwell
TagsApps

I wrote about this in more detail in a blog post, but I wanted to share an update I made to EyeDock's oblique crossed cylinders calculator. It still does the calculation the same (optical fundamentals don't change, after all), but you can now specify which lens you're using as a trial. This does not affect the calculation. However, it does allow my program to use EyeDock's contact lens database to let you know the closest set of parameters to the calculated result. So, it will round to the closest sphere power, cylinder power, and axis, all while doing smart things like maintaining spherical equivalent, etc.

Here's a little video explaining the calculator and this new feature.


Posted
AuthorTodd Zarwell

One does not become a professional lawn mower overnight. All kids dream of the bright lights, the glory, the big contracts, but few are willing to put forth the effort required to make it to the big time.  

You don't have to start at a young age, but it helps. Take Aiden, for example. He started training at two years old and has already logged more hours than many people 10 times his age. His chances of making a traveling mowing team by age four are quite good. There, he'll refine his skills by competing against the best of the best and, by the time he's 18, should snag a lawn mowing scholarship to a top university program. 

And, with hard work, dedication, and a little luck - such as avoiding any career ending injuries - perhaps Aiden will be drafted by a pro team some day. Of course, going pro is a whole other level, but, in the right system complete with veteran leadership, good coaching, lots of film study, I'm convinced my boy could be a star. And hopefully he'll buy me a new house. Or at least pay off my school loans.

Check out the gallery below to see some of AIden's training techniques.

 

And, lastly, a video illustrating his dedication to his craft.

Posted
AuthorTodd Zarwell

Six months ago, I wrote about my thoughts on the difficulties of teaching kids to write code. There were a few iPad apps that seemed to have potential to introduce kids to programming.

Unfortunately I've had a hard time finding a way to introduce my sons to these apps. After all, it's kind of a slippery slope. I want this to be fun, and I'm afraid if it seems like too much of a chore right off the bat it might be a while before I can try again. Also, when you open up the iPad there are potential distractions just two clicks away. If the app comes off as boring or too educational I'll get a "can I play Minecraft instead?" within minutes.

So, I've been biding my time and waiting for the right moment. Then, lo and behold, we were signing my oldest son up for supper activities this Spring when I saw an appealing option: "Coding with Kodable". Ooh, that sounded interesting. After reading the description I learned that Kodable is another "learn to code" app in the same vein as the ones I mentioned in my blog post last December. Well, of course we signed up for it and my son will be finishing up his "camp" today.

It has gone really well. He did it with other kids his age, so it was fun, and he really did learn core concepts in programming. Today was the first time I dropped him off at his class, so I hung around for a few minutes and watched my son work through the app's puzzles. I was pretty impressed with what I saw.

Now, keep in mind that we're talking about 7 year olds here. They're still learning how to write and spell, so typing in complicated blocks of code is out of the question. The goal is to start with the basics.

What is a computer program? It's a sequential list of instructions that tell a computer what to do. So, that's where Kodables starts. In this case, the instructions are geared towards guiding a "Fuzz" through a maze.  (The optometrist in me can't help but notice this is also a great exercise for laterality / directionality, spatial reasoning, etc). The child simply drags a series of arrows onto the screen to guide their character though its course. Just like in programming, the order of the instructions counts. Also, there can be more than one way to accomplish a task, but there is often a way that involves the least amount of instructions or takes a better approach (in Kodables, the better approach is the one that leads the Fuzz past the most coins). 

The next major concept is conditional statements. A program needs accept input then make a decision as to what to do next. In most programming languages this is done in an IF/THEN statement, eg) IF (weight > 200) THEN diet. In codables the condition the child can apply a color to their arrows that essentially says "if your Fuzz encounters a red square turn down".

Conditional statements on Kodable. The instructions are the arrows in the top left side of the screen. Note the arrow with the red background - this is a conditional statement.

Conditional statements on Kodable. The instructions are the arrows in the top left side of the screen. Note the arrow with the red background - this is a conditional statement.

 

As people improve at coding they learn an important lesson: Don't work any harder than you have to. You oftentimes find yourself writing out the same sets of instructions multiple times. Whenever you find yourself in this situation you have to ask yourself if there's an easier way. Working smart,  not just hard, can result in huge time savings. In programming, two fundamental concepts that can help with this are loops and functions.

Loops can be used when repeating the same task two or more times. Consider the following maze on Kodables:

Loops on Kodable. 

Loops on Kodable. 

The instructions would go like this:

  1. go right
  2. go up
  3. go right
  4. go up
  5. go right

That wasn't too bad to type out, but what if we had to do it ten more times? Or a hundred more times? This is where loops come in handy. A lop would essentially say:

  1. go right
  2. go up
  3. repeat the above steps 100 times

Functions are very similar in a lot of ways, except we don't necessarily duplicate the same instructions repeatedly. Instead, we save a set of instructions as a block, or function, that we can use, or "call", at any time. Consider this Kodable maze:

Functions in Kodable. Note the three steps that are included in the function (seen to the right of the curly brackets { } on the right hand side)

Functions in Kodable. Note the three steps that are included in the function (seen to the right of the curly brackets { } on the right hand side)

To get through this maze the instructions would look like this:

  1. go right
  2. at the pink box, turn down
  3. go right
  4. go up 
  5. go right
  6. at the pink box, turn down
  7. go right

Notice any patterns here? Steps 1-3 are identical to steps 5-7. The "programmer" astutely noticed this and made a function. The function is located on the right side by the curly brackets { }, and contains the same block of instructions as steps 1-3 above. So, the new instructions will look like this:

  1.  run the function
  2. go up
  3. run the function

It doesn't look like much, but this is one of hallmarks of efficient coding and can save tons of lines of code, not to mention time,  as programs get longer and longer.

A Kodable bug

A Kodable bug

Another very important feature kids will learn from Kodables is debugging. Coders rarely write a perfect program on the first try. Programming is very much a trial and error process: Write some code, run it, see where it screwed up, rewrite some code, and repeat. Just like real coding, you can run your program and watch each step as it executes to localize where the problem is coming fro. In Kodables there's segments where it purposely gives you a program with errors in it, and actually places a cartoon bug on the maze at the location of the problem. When you fix the programming "bug", your Fuzz rolls over the cartoon bug and squashes it. I know from experience there's nothing more satisfying than squashing those bugs.

In summary, Kodables seems to be a great way to get kids started in programming. It teaches them to look at a problem and break it into little parts, then give the computer stepwise instructions to solve the problem. It teaches concepts such as conditionals, loops, and functions. It also teaches debugging and, as a result, the acceptance of the inevitability of errors and the dedication needed to troubleshoot and fix your bugs.

In the future, kids that want to continue with coding will need to learn a programming language and its syntax. However, in my opinion, learning the basics of programming is much more important. And, after learning one programming language, picking up others is relatively simple once you master the fundamentals.

 

PS My 5 year old came along with me when we dropped my 7 year old off at Kodables camp today. After he saw his big brother solving puzzles on an iPad he wanted to do the same thing. We went to a coffee shop, downloaded the app, and spent an hour and a half "programming". He picked it up very quickly and we had a lot of fun together.



Posted
AuthorTodd Zarwell
CategoriesTech

I've rewritten my contact lens calculator on EyeDock. The new version does a better bob of showing its calculations by displaying information on optic crosses. It's also more flexible with how it accepts keratometry and refraction input. Lastly, I've added a SPE / CPE lens calculator that uses Thomas Quinn OD's nomograms (the same ones we used to create the GPLI calculator). 

Here's a little video introduction. I hope you find it useful!

- Todd


Posted
AuthorTodd Zarwell