January 2018 Gratitudes

Comments [0]

2/4
Today I am grateful for coffee.

2/3
Today I am grateful for my first visit to Kingston, ON and Queen's University.

2/2
Today I am grateful for my new condo.

2/1
Today I am grateful for dinner with Esteban last night.

1/31
Today I am grateful for a chance to deliver 2 guest lectures yesterday at the University of Illinois and for all the questions during and after each lecture.

1/30
Today I am grateful to be invited to speak at Illinois Pulse Week last night and for a great audience that stayed 45 minutes late asking questions.

1/29
Today I am grateful for a gift of a new pair of shoes.

1/28
Today I am grateful that I've lost 30 pounds in the last year.

1/27
Today I am grateful for coffee with Keith yesterday.

1/26
Today I am grateful that the professors I deal with are appreciative of the work I'm doing and the programs we are offering.

1/25
Today I am grateful for dinner last night with Stephen and Angel.

1/24
Today I am grateful to attend an exciting Spurs-Cavs game last night.

1/23
Today I am grateful to see MSU play basketball at Illinois last night - probably the only game I will see in-person this year.

1/22
Today I am grateful for
-my first time attending U of T Hacks
-an upgrade on my flight home last night

1/21
Today I am grateful for my first taste of sushi burrito yesterday.

1/20
Today I am grateful to all the students who stayed at my AI workshop past 1:30AM last night.

1/19
Today I am grateful to spend yesterday with my old team.

1/18
Today I am grateful for 2 years in my current apartment.

1/17
Today I am grateful that my work takes me to so many amazing places.

1/16
Today I am grateful for dinner with Josh last night.

1/15
Today I am grateful to Dr. Martin Luther King, Jr., who called out injustice where he saw it and advanced an important struggle that continues today.

1/14
Today I am grateful for my first visit to a Persian restaurant.

1/13
Today I am grateful to travel safely from Sandusky to Chicago to Dallas to Vancouver in less than 24 hours.

1/12
Today I am grateful for my 11th #CodeMash and all who worked hard to make it excellent.

1/11
Today I am grateful to Jennifer and Matt for answering my Machine Learning questions yesterday.

1/10
Today I am grateful to see so many old friends yesterday at #CodeMash.

1/9
Today I am grateful to attend an #MIGANG meeting last night in Michigan and drive to Ohio after with Jennifer, Ondrej, Jonathan, Gaines, and Seth.

1/8
Today I am grateful to watch Black Mirror last night with Ondrej, Desislava, Gaines, and Mary.

1/7
Today I am grateful I've made it to the gym every day I was home.

1/6
Today I am grateful for a birthday lunch yesterday with Shelly and Jason.

1/4
Today I am grateful for a good night sleep last night.

1/3
Today I am grateful for my slow cooker.

1/2
Today I am grateful to Brent for helping me with my Azure questions yesterday.

1/1
Today I am grateful for:
-a few days in California with my boys
-seeing the Chargers
-Raiders game yesterday at the StubHub Center
-An upgrade to First Class on my flight home last night



ElfstonesOfShannaraThe Elfstones of Shannara is the second book of Terry Brooks’s Shannara series.

It begins years after The Sword of Shannara. The magical Ellcrys tree - created by the elves millennia earlier to imprison the evil demons - has begun to die, allowing the demons to regain their strength and attack men and elves.

Wil Ohmsford - grandson of Shea Ohmsford, hero of the first novel - is assigned the task of re-planting the Ellcrys. He needs the help of the elven princess Amberle, who is chosen to protect the magical tree, but has run away from her king and family. To protect her on his quest, he uses the power of the mystical elfstones left to him by his grandfather.

It becomes a race for Wil and Amberle to find the hidden Ellcrys seed and restore the Ellcrys before the emboldened demons attack and destroy men and elves of the Four Lands.

Terry Brooks knows how to tell a story, but it troubles me that he borrows so much from JRR Tolkien. It's not just that his world is populated with elves and dwarves. Major parts of the story are lifted directly from Tolkien. The young, reluctant hero goes on a quest to save the world from evil creatures, armed with a magical talisman that was left to him by an older relative, who went on a similar quest in an earlier book. We could easily substitute Bilbo, Frodo, and the Ring for Wil, Shea, and the Elfstones.

But, the stories are entertaining if not told with Tolkien's magic. It's a good introduction to the world of fantasy for those who want something more accessible than Lord of the Rings.



Azure provides several ways of managing resources through scripting users. You can write scripts in either PowerShell (a popular Windows tool for managing servers and IAT resources) or CLI (a Bash-like scripting language that runs on Windows, Linux, and MacOS).

To use these tools, you need to have them installed locally, along with any support tools, such as the Azure PowerShell commandlets.

Until now.

Recently, Microsoft released the Azure Cloud Shell - a browser-based command-line interface built into the Azure portal. By opening a Cloud Shell from the Azure Portal, you can execute PowerShell or CLI scripts from within your browser, without installing anything.

To open Cloud Shell, navigate to the Azure portal and click the [Cloud Shell] button (Fig. 1) on the top tool bar.

CS01CloudShellButton
Fig. 1

It may take a minute to retrieve and connect to a Cloud Shell environment (Fig. 2), but soon you will see a window with a command prompt, as Shown in Fig. 3.

CS02-BashTerminal
Fig. 2

CS03-CLICloudShell
Fig. 3

The Cloud Shell in the image is configured to run CLI scripts. You can tell this by the dropdown in the window's top left corner. You can also run PowerShell scripts in a Cloud Shell window. To change the script types, click the top left dropdown and select your desired scripting language, as shown in Fig. 4.

CS04-ChangeScriptType
Fig. 4

Fig. 5 shows the Cloud Shell with PowerShell selected.

CS05-PowerShellCloudShell
Fig. 5

You don't need to log into the Cloud Shell environment. It will assume the account from which it was launched.

But you can view, create, and manage Azure resources. For example, from the Bash shell, type

az group list -o table

To see a list of all Resource Groups

or

az group create -l southeastus -n myrg

to create a new resource group named "myrg" in the Southeast US region.

You can even do other bash commands, such as ssh into an Azure Linux VM.

Cloud Shell automatically creates a container within an Azure VM to host your session. Although this container is destroyed shortly after you disconnect, Cloud Shell also creates a storage account to persist files or settings you use when using this interface, so they will be there when you return.

Azure Cloud Shell provides an environment for you to execute automation scripts and other administrative functions.



December 2017 Gratitudes

Comments [0]

12/1
Today I am grateful to see an exciting Hawks-Cavs game with

12/2
Today I am grateful for dinner last night with Shawn and Resa.

12/3
Today I am grateful to attend DataSciConf in Atlanta for the first time.

12/4
Today I am grateful for temperatures in the 50s in Chicago in December.

12/5
Today I am grateful for great seats at my second Atlanta Hawks home game in the past week.

12/6
Today I am grateful for an excellent dinner last night in midtown Atlanta with my team.

12/7
Today I am grateful for a meaningful and enjoyable offsite with my team in Atlanta this week.

12/8
Today I am grateful to attend the Chicago User Group Holiday Party last night.

12/9
Today I am grateful for a kind and completely unexpected email last night.

12/9
Today I am grateful for:
-The Uber driver who picked me up yesterday and took me to the airport when my Uber driver ran out of gas on the way.
-The "Lights in the Heights" festival last night in Houston.

12/10
Today I am grateful for:
-The hospitality and generosity of Paul
-Attending a home Texans game for the first time.

12/12
Today I am grateful to see an exciting Pelicans - Rockets game last night - my first time at the Toyota Center!

12/13
Today I am grateful to attend a home University of Texas basketball game for the first time.

12/14
Today I am grateful to spend a few days in Texas and meeting with folks at the University of Texas in Austin.

12/15
Today I am grateful for the holiday party hosted by my apartment building last night.

12/16
Today I am grateful to spend some time at home.

12/17
Today I am grateful to spend yesterday with my sons.

12/18
Today I am grateful to take Nick and Tim to a Black Hawks game last night - their first visit to the United Center.

12/19
Today I am grateful for an unseasonably warm Chicago December.

12/20
Today I am grateful for my first visit to the Argonne National Laboratory to attend a reception for David Danielson - clean energy entrepreneur and former Assistant Secretary of Energy.

12/21
Today I am grateful to everyone who helped me get to 500 episodes on #TechnologyAndFriends
https://youtu.be/SQf8WKKYqlM

12/22
Today I am grateful to see Roy Ayers in concert last night on my first visit to The Promontory in Hyde Park.

12/22
Today I am grateful for 3 Personal Training sessions this week - the last 3 of 2017!

12/24
Today I am grateful for a Christmas Eve snowfall; and the fact that I am not driving in it.

12/25
Today I am grateful that we still celebrate the birth of Jesus Christ after all these years.

12/26
Today I am grateful to spend Christmas with my family.

12/27
Today I am grateful to see an excellent Roy Hargrove concert last night at the Jazz Showcase in the South Loop.

12/28
Today I am grateful to see a Lakers-Grizzlies game last night on my first visit to the Staples Center.

12/29
Today I am grateful for:
-Lunch yesterday with my cousin Barbara in San Juan Capistrano
-Watching a Spartan victory in the Holiday Bowl from the 50-yard-line with my son Tim

12/30
Today I am grateful to see Nick's Williams College basketball team play for the first time last night in California.

12/31
Today I am grateful for lunch yesterday with my cousin Bob.

1/1
Today I am grateful for:
-a few days in California with my boys
-seeing the Chargers-Raiders game yesterday at the StubHub Center
-An upgrade to First Class on my flight home last night

1/2
Today I am grateful to Brent for helping me with my Azure questions yesterday.

1/3
Today I am grateful for my slow cooker.

1/4
Today I am grateful for a good night sleep last night.

1/6
Today I am grateful for a birthday lunch yesterday with Shelly and Jason.

1/7
Today I am grateful I've made it to the gym every day I was home.


2017 in Review

Comments [0]

2017 was a year of change. I started a new job; I traveled for the first time to South America, the Czech Republic, Iowa, Oregon, and Los Angeles; I returned to Canada for the first time in 10+ years; my son Tim graduated and began his professional career; and my son Nick accepted a new job in Massachusetts.

I'll start with me.

New Job

Microsoft  went through a major reorganization last year and it greatly affected my department and my job. I moved to a new team that is focused on helping professors at Top Computer Science universities teach their students about cloud computing. This role involves even more travel than my last one. For the past few months, I've been visiting schools around North America and my calendar for the next 2 months is filled with campus visits for hackathons, guest lectures, workshops, and meetings with students, and professors. I won't be home much in January and February.

Travel

I traveled more and farther in 2017 than I have in a long time (if ever). I visited 7 different countries (Romania, Sweden, The Czech Republic, Uruguay, Argentina, Canada, and the US) and 17 states. It was my first visit to the Czech Republic, Uruguay, and Argentina.

Prague has long been on my list of places to visit so I was thrilled to finally get there and I enjoyed the hospitality of Gael Fraiteur and Brit King. Gael and I drove down to Český Krumlov - a small village in southern Bohemia preserved as it was in the 18th century - where we spent a night and explored castles, museums, and restaurants.

I was happy to accept an invitation to speak at .NET Conf UY, primarily because it was my first trip to South America. After a few days in Montevideo, Uruguay, I took a ferry to Buenos Aires, where I spent an afternoon exploring the city on foot. In May, I scheduled tour to speak at 4 different user groups in 3 days in Iowa. My friend Javier helped me plan the trip and I was excited for my first visit to the Hawkeye State. 

In 2017, I got serious about my goal of seeing every home stadium and arena of the 4 major professional sports league. I visited 3 NFL stadiums, 4 NBA arenas, and 2 NHL arenas last year. With 55 places remaining, I will need to accelerate this process.

In January, I flew to San Francisco, where my friend Sara picked me up and together we drove 7 hours to a small town in southwest Oregon to attend the funeral of the wife of an old friend. The next day, we attended the funeral and a dinner and repeated the trip in reverse. We were fortunate to have flexible enough schedules to make this trip and I'm really glad we did. And I got to know Sara a lot better on the trip.

Live Music

I made it a point to see a lot of live music in 2017. Most of the shows  (Stanley Clarke, Buddy Guy, Guy King, Ladysmith Black Mambazo, Booker T. Jones, Marcia Ball, Delbert McClinton, Kris Kristofferson, Al Stewart, Jean-Luc Ponty, Benny Golson, Paul Weller, and Roy Ayers) were at small clubs in Chicago (SPACE, Buddy Guy's Legends, Old Town School of Folk Music, SPACE, City Winery, Jazz Showcase, House of Blues, and The Promontory), but I also saw Eric Church and Tim McGraw / Faith Hill at the cavernous Allstate Arena.

My Two Sons

My two sons also had some major changes in their lives.

Shortly after graduating from Indiana University with a degree in Informatics, Tim accepted a job with Enkay Tech -  an IT consulting company outside of Chicago. He lived with me for a few months before renting a house in Wrigleyville. Spending time with hi was one of the highlights of my summer.

After 2 years serving as Director of Basketball Operations at Southern Illinois University - Edwardsville, Nick accepted a position as an assistant coach at Williams College in Williamstown, MA. He moved in the fall and his team have been ranked as high as #5 in Division 3. In December, I was able to see Williams play 2 games at a tournament in Thousand Oaks CA.

Mostly Good, Some Bad

Although most of 2017 was good to me, not everything was awesome. My mother passed away in June. A few weeks later, I was diagnosed with skin cancer, which was successfully removed. Not long after, a relationship ended after over a year of dating. Each incident was magnified because they came in quick succession, but I've recovered from them. My family and I were somewhat prepared for our mother's passing. She was 85 and the death of my father and sister in the past few years forced us to consider the inevitable loss of other loved ones. I am left with fond memories of her and of the girl I lost and this helps. And my follow-up appointment showed no sign of skin cancer.

Looking Ahead

2017 was an amazing year of growth for me personally. The changes are accelerating into 2018. My calendar is already full for the first 2 months and I am looking forward to the future with optimism.



December 2016 Gratitudes

Comments [0]

12/31
Today I am grateful for lunch yesterday with my cousin Bob.

12/30
Today I am grateful to see Nick's Williams College basketball team play for the first time last night in California.

12/29
Today I am grateful for:
-Lunch yesterday with my cousin Barbara in San Juan Capistrano
-Watching a Spartan victory in the Holiday from the 50-yard-line with my son Tim

12/28
Today I am grateful to see a Lakers-Grizzlies game last night on my first visit to the Staples Center.

12/27
Today I am grateful to see an excellent Roy Hargrove concert last night at the Jazz Showcase in the South Loop.

12/26
Today I am grateful to spend Christmas with my family.

12/25
Today I am grateful that we still celebrate the birth of Jesus Christ after all these years.

12/24
Today I am grateful for a Christmas Eve snowfall; and the fact that I am not driving in it.

12/23
Today I am grateful for 3 Personal Training sessions this week - the last 3 of 2017!

12/22
Today I am grateful to see Roy Ayers in concert last night on my first visit to The Promontory in Hyde Park.

12/21
Today I am grateful to everyone1 who helped me get to 500 episodes on #TechnologyAndFriends

12/20
Today I am grateful for my first visit to the Argonne National Laboratory to attend a reception for David Danielson - clean energy entrepreneur and former Assistant Secretary of Energy.

12/19
Today I am grateful for an unseasonably warm Chicago December.

12/18
Today I am grateful to take Nick and Tim to a Black Hawks game last night - their first visit to the United Center.

12/17
Today I am grateful to spend yesterday with my sons.

12/16
Today I am grateful to spend some time at home.

12/15
Today I am grateful for the holiday party hosted by my apartment building last night.

12/14
Today I am grateful to spend a few days in Texas and meeting with folks at the University of Texas in Austin.

12/13
Today I am grateful to attend a home University of Texas basketball game for the first time.

12/12
Today I am grateful to see an exciting Pelicans-Rockets game last night - my first time at the Toyota Center!

12/11
Today I am grateful for:
-The hospitality and generosity of Paul
-Attending a home Texans game for the first time.

12/10
Today I am grateful for:
-The Uber driver who picked me up yesterday and took me to the airport when my Uber driver ran out of gas on the way.
-The "Lights in the Heights" festival last night in Houston.

12/09
Today I am grateful for a kind and completely unexpected email last night.

12/08
Today I am grateful to attend the Chicago User Group Holiday Party last night.

12/07
Today I am grateful for a meaningful and enjoyable offsite with my team in Atlanta this week.

12/06
Today I am grateful for an excellent dinner last night in midtown Atlanta with my team.

12/05
Today I am grateful for great seats at my second Atlanta Hawks home game in the past week.

12/4
Today I am grateful for temperatures in the 50s in Chicago in December.


As I discussed in a previous article, Microsoft Cognitive Services includes a set of APIs that allow your applications to take advantage of Machine Learning in order to analyze, image, sound, video, and language. One of these APIs is a REST web service that can determine the words and punctuation contained in a picture. This is accomplished by a simple REST web service call.

The Cognitive Services Optical Character Recognition (OCR) service is part of the Custom Vision API. It takes as input a picture of text and returns the words found in the image.

To get started, you will need an Azure account and a Cognitive Services Vision API key.

If you don't have an Azure account, you can get a free one at https://azure.microsoft.com/free/.

Once you have an Azure Account,  follow the instructions in this article to generate a Cognitive Services Computer Vision key.

To use this API, you simply have to make a POST request to the following URL:
https://[location].api.cognitive.microsoft.com/vision/v1.0/ocr

where [location] is the Azure location where you created your API key (above).

Optionally, you can add the following 2 querystring parameters to the URL:

  • Language: the 2-digit language abbreviation abbreviation. Use “en” for English. Currently, 25 languages are supported. If omitted, the service will attempt to auto-detect the language
  • detectOrientation: Set this to “true” if you want to support upside-down or rotated images.

The HTTP header of the request should include the following:

Ocp-Apim-Subscription-Key.     
The Cognitive Services Computer Vision key you generated above.

Content-Type

This tells the service how you will send the image. The options are:

  • application/json
  • application/octet-stream
  • multipart/form-data

If the image is accessible via a public URL, set the Content-Type to application/json and send JSON in the body of the HTTP request in the following format

{"url":"imageurl"}
where imageurl is a public URL pointing to the image. For example, to perform OCR on an image of an Edgar Allen Poe poem, submit the following JSON:

{"url": "http://media.tumblr.com/tumblr_lrbhs0RY2o1qaaiuh.png"}

DreamWithinADream

If you plan to send the image itself to the web service, set the content type to either "application/octet-stream" or “multipart/form-data” and submit the binary image in the body of the HTTP request.

The full request looks something like:  

POST https://westus.api.cognitive.microsoft.com/vision/v1.0/ocr HTTP/1.1
Content-Type: application/json
Host: westus.api.cognitive.microsoft.com
Content-Length: 62
Ocp-Apim-Subscription-Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{ "url": "http://media.tumblr.com/tumblr_lrbhs0RY2o1qaaiuh.png" }

For example, passing a URL with the following picture:

 DreamWithinADream
  (found online at http://media.tumblr.com/tumblr_lrbhs0RY2o1qaaiuh.png)

returned the following data: 

{
  "textAngle": 0.0,
  "orientation": "NotDetected",
  "language": "en",
  "regions": [
    {
      "boundingBox": "31,6,435,478",
      "lines": [
        {
          "boundingBox": "114,6,352,23",
          "words": [
            {
              "boundingBox": "114,6,24,22",
              "text": "A"
            },
            {
              "boundingBox": "144,6,93,23",
               "text": "Dream"
            },
            {
               "boundingBox": "245,6,95,23",
              "text": "Within"
            },
            {
              "boundingBox": "350,12,14,16",
              "text": "a"
            },
            {
              "boundingBox": "373,6,93,23",
              "text": "Dream"
            }
          ]
        },
        {
           "boundingBox": "31,50,187,16",
          "words": [
             {
              "boundingBox": "31,50,31,12",
               "text": "Take"
            },
            {
              "boundingBox": "66,50,23,12",
              "text": "this"
             },
            {
              "boundingBox": "93,50,24,12",
              "text": "kiss"
            },
            {
               "boundingBox": "121,54,33,12",
              "text": "upon"
            },
            {
              "boundingBox": "158,50,19,12",
              "text": "the"
            },
             {
              "boundingBox": "181,50,37,12",
               "text": "brow!"
            }
          ]
        },
        {
          "boundingBox": "31,67,194,16",
          "words": [
             {
              "boundingBox": "31,67,31,15",
               "text": "And,"
            },
            {
              "boundingBox": "67,67,12,12",
              "text": "in"
             },
            {
              "boundingBox": "82,67,46,16",
              "text": "parting"
            },
            {
              "boundingBox": "132,67,31,12",
              "text": "from"
            },
            {
              "boundingBox": "167,71,25,12",
              "text": "you"
            },
             {
              "boundingBox": "195,71,30,11",
               "text": "now,"
            }
          ]
        },
         {
          "boundingBox": "31,85,159,12",
          "words": [
            {
              "boundingBox": "31,85,32,12",
               "text": "Thus"
            },
            {
               "boundingBox": "67,85,35,12",
              "text": "much"
            },
            {
              "boundingBox": "107,86,16,11",
              "text": "let"
            },
             {
              "boundingBox": "126,89,20,8",
              "text": "me"
            },
            {
              "boundingBox": "150,89,40,8",
              "text": "avow-"
            }
          ]
        },
        {
          "boundingBox": "31,102,193,16",
          "words": [
            {
              "boundingBox": "31,103,26,11",
              "text": "You"
             },
            {
              "boundingBox": "61,106,19,8",
              "text": "are"
            },
            {
               "boundingBox": "84,104,21,10",
              "text": "not"
            },
            {
              "boundingBox": "109,106,44,12",
              "text": "wrong,"
            },
             {
              "boundingBox": "158,102,27,12",
               "text": "who"
            },
            {
              "boundingBox": "189,102,35,12",
              "text": "deem"
             }
          ]
        },
        {
          "boundingBox": "31,120,214,16",
          "words": [
            {
               "boundingBox": "31,120,29,12",
              "text": "That"
            },
            {
              "boundingBox": "64,124,21,12",
              "text": "my"
            },
            {
              "boundingBox": "89,121,29,15",
              "text": "days"
            },
            {
              "boundingBox": "122,120,30,12",
              "text": "have"
            },
            {
              "boundingBox": "156,121,30,11",
              "text": "been"
            },
            {
               "boundingBox": "191,124,7,8",
              "text": "a"
            },
            {
              "boundingBox": "202,121,43,14",
              "text": "dream;"
            }
           ]
        },
        {
          "boundingBox": "31,138,175,16",
          "words": [
            {
              "boundingBox": "31,139,22,11",
              "text": "Yet"
            },
             {
              "boundingBox": "57,138,11,12",
               "text": "if"
            },
            {
              "boundingBox": "70,138,31,16",
              "text": "hope"
             },
            {
              "boundingBox": "105,138,21,12",
              "text": "has"
            },
            {
               "boundingBox": "131,138,37,12",
              "text": "flown"
            },
            {
              "boundingBox": "172,142,34,12",
              "text": "away"
            }
          ]
        },
        {
          "boundingBox": "31,155,140,16",
          "words": [
            {
              "boundingBox": "31,156,13,11",
              "text": "In"
             },
            {
              "boundingBox": "48,159,8,8",
               "text": "a"
            },
            {
               "boundingBox": "59,155,37,16",
              "text": "night,"
            },
            {
              "boundingBox": "100,159,14,8",
              "text": "or"
            },
             {
              "boundingBox": "118,155,12,12",
              "text": "in"
            },
            {
              "boundingBox": "134,159,7,8",
              "text": "a"
            },
             {
              "boundingBox": "145,155,26,16",
               "text": "day,"
            }
          ]
        },
         {
          "boundingBox": "31,173,144,15",
          "words": [
            {
              "boundingBox": "31,174,13,11",
              "text": "In"
            },
            {
               "boundingBox": "48,177,8,8",
              "text": "a"
             },
            {
              "boundingBox": "59,173,43,15",
              "text": "vision,"
            },
             {
              "boundingBox": "107,177,13,8",
              "text": "or"
            },
            {
              "boundingBox": "124,173,12,12",
              "text": "in"
            },
            {
              "boundingBox": "140,177,35,11",
               "text": "none,"
            }
          ]
        },
        {
          "boundingBox": "31,190,180,16",
          "words": [
            {
              "boundingBox": "31,191,11,11",
              "text": "Is"
            },
            {
               "boundingBox": "47,190,8,12",
              "text": "it"
            },
            {
              "boundingBox": "59,190,58,12",
              "text": "therefore"
            },
             {
              "boundingBox": "121,190,19,12",
               "text": "the"
            },
            {
               "boundingBox": "145,191,23,11",
              "text": "less"
             },
            {
              "boundingBox": "173,191,38,15",
              "text": "gone?"
            }
          ]
        },
        {
          "boundingBox": "31,208,150,12",
          "words": [
            {
              "boundingBox": "31,208,20,12",
              "text": "All"
            },
             {
              "boundingBox": "55,208,24,12",
               "text": "that"
            },
            {
              "boundingBox": "83,212,19,8",
              "text": "we"
             },
            {
              "boundingBox": "107,212,19,8",
              "text": "see"
            },
            {
               "boundingBox": "131,212,13,8",
              "text": "or"
            },
            {
              "boundingBox": "148,212,33,8",
              "text": "seem"
            }
           ]
        },
        {
          "boundingBox": "31,226,194,12",
          "words": [
            {
              "boundingBox": "31,227,11,11",
              "text": "Is"
            },
             {
              "boundingBox": "46,226,21,12",
               "text": "but"
            },
            {
              "boundingBox": "71,230,7,8",
              "text": "a"
             },
            {
              "boundingBox": "82,226,40,12",
              "text": "dream"
            },
            {
               "boundingBox": "126,226,41,12",
              "text": "within"
            },
            {
              "boundingBox": "171,230,7,8",
              "text": "a"
            },
             {
              "boundingBox": "182,226,43,12",
               "text": "dream."
            }
          ]
        },
         {
          "boundingBox": "31,261,133,12",
          "words": [
            {
              "boundingBox": "31,262,5,11",
               "text": "I"
            },
            {
               "boundingBox": "41,261,33,12",
              "text": "stand"
             },
            {
              "boundingBox": "78,261,32,12",
              "text": "amid"
            },
            {
              "boundingBox": "114,261,19,12",
              "text": "the"
            },
            {
              "boundingBox": "137,265,27,8",
              "text": "roar"
            }
          ]
        },
        {
          "boundingBox": "31,278,169,15",
          "words": [
            {
              "boundingBox": "31,278,18,12",
              "text": "Of"
             },
            {
              "boundingBox": "52,282,7,8",
              "text": "a"
            },
            {
               "boundingBox": "63,278,95,12",
              "text": "surf-tormented"
            },
            {
              "boundingBox": "162,278,38,15",
              "text": "shore,"
            }
          ]
        },
        {
          "boundingBox": "31,296,174,15",
          "words": [
            {
              "boundingBox": "31,296,28,12",
              "text": "And"
             },
            {
              "boundingBox": "63,297,4,11",
              "text": "I"
            },
            {
               "boundingBox": "72,296,28,12",
              "text": "hold"
            },
            {
              "boundingBox": "104,296,41,12",
              "text": "within"
            },
             {
              "boundingBox": "149,300,20,11",
               "text": "my"
            },
            {
              "boundingBox": "173,296,32,12",
              "text": "hand"
             }
          ]
        },
        {
          "boundingBox": "31,314,169,16",
          "words": [
            {
               "boundingBox": "31,314,42,12",
              "text": "Grains"
            },
            {
              "boundingBox": "78,314,15,12",
              "text": "of"
            },
             {
              "boundingBox": "95,314,19,12",
              "text": "the"
            },
            {
              "boundingBox": "119,315,43,15",
              "text": "golden"
             },
            {
              "boundingBox": "167,314,33,12",
              "text": "sand-"
            }
          ]
         },
        {
          "boundingBox": "31,331,189,16",
           "words": [
            {
              "boundingBox": "31,332,31,11",
              "text": "How"
            },
             {
              "boundingBox": "66,331,28,12",
              "text": "few!"
            },
            {
              "boundingBox": "99,333,20,14",
              "text": "yet"
            },
            {
              "boundingBox": "123,331,27,12",
               "text": "how"
            },
            {
               "boundingBox": "154,331,28,16",
              "text": "they"
            },
            {
              "boundingBox": "186,335,34,12",
              "text": "creep"
            }
           ]
        },
        {
          "boundingBox": "31,349,206,16",
          "words": [
            {
              "boundingBox": "31,349,55,16",
              "text": "Through"
            },
            {
              "boundingBox": "90,353,20,11",
               "text": "my"
            },
            {
               "boundingBox": "115,349,44,16",
              "text": "fingers"
            },
            {
              "boundingBox": "163,351,12,10",
              "text": "to"
            },
             {
              "boundingBox": "179,349,20,12",
               "text": "the"
            },
            {
              "boundingBox": "203,350,34,15",
              "text": "deep,"
             }
          ]
        },
        {
          "boundingBox": "31,366,182,16",
          "words": [
            {
               "boundingBox": "31,366,39,12",
              "text": "While"
            },
            {
              "boundingBox": "74,367,5,11",
              "text": "I"
            },
            {
              "boundingBox": "83,370,39,12",
              "text": "weep-"
            },
            {
              "boundingBox": "126,366,36,12",
              "text": "while"
             },
            {
              "boundingBox": "166,367,5,11",
              "text": "I"
            },
            {
               "boundingBox": "175,367,38,15",
              "text": "weep!"
            }
          ]
        },
        {
          "boundingBox": "31,384,147,16",
          "words": [
            {
               "boundingBox": "31,385,11,11",
              "text": "O"
            },
            {
              "boundingBox": "47,384,31,12",
              "text": "God!"
            },
             {
              "boundingBox": "84,388,21,8",
               "text": "can"
            },
            {
              "boundingBox": "110,385,4,11",
              "text": "I"
             },
            {
              "boundingBox": "119,386,20,10",
              "text": "not"
            },
            {
               "boundingBox": "144,388,34,12",
              "text": "grasp"
            }
          ]
        },
        {
          "boundingBox": "31,402,170,16",
          "words": [
            {
              "boundingBox": "31,402,37,12",
              "text": "Them"
            },
            {
              "boundingBox": "72,402,29,12",
              "text": "with"
            },
            {
              "boundingBox": "105,406,7,8",
               "text": "a"
            },
            {
              "boundingBox": "116,402,42,16",
              "text": "tighter"
            },
            {
              "boundingBox": "162,403,39,15",
              "text": "clasp?"
            }
           ]
        },
        {
          "boundingBox": "31,419,141,12",
          "words": [
            {
              "boundingBox": "31,420,11,11",
              "text": "O"
            },
             {
              "boundingBox": "47,419,31,12",
               "text": "God!"
            },
            {
              "boundingBox": "84,423,21,8",
              "text": "can"
             },
            {
              "boundingBox": "110,420,4,11",
              "text": "I"
            },
            {
               "boundingBox": "119,421,20,10",
              "text": "not"
            },
            {
              "boundingBox": "144,423,28,8",
              "text": "save"
            }
           ]
        },
        {
          "boundingBox": "31,437,179,16",
          "words": [
            {
              "boundingBox": "31,438,26,11",
              "text": "One"
            },
            {
              "boundingBox": "62,437,31,12",
               "text": "from"
            },
            {
               "boundingBox": "97,437,19,12",
              "text": "the"
             },
            {
              "boundingBox": "120,437,45,16",
              "text": "pitiless"
            },
             {
              "boundingBox": "169,438,41,11",
               "text": "wave?"
            }
          ]
        },
        {
          "boundingBox": "31,454,161,12",
          "words": [
            {
              "boundingBox": "31,455,11,11",
               "text": "Is"
            },
            {
               "boundingBox": "47,454,15,12",
              "text": "all"
             },
            {
              "boundingBox": "66,454,25,12",
              "text": "that"
            },
            {
              "boundingBox": "94,458,19,8",
              "text": "we"
            },
            {
              "boundingBox": "118,458,19,8",
              "text": "see"
            },
             {
              "boundingBox": "142,458,13,8",
               "text": "or"
            },
            {
              "boundingBox": "159,458,33,8",
              "text": "seem"
             }
          ]
        },
        {
          "boundingBox": "31,472,185,12",
          "words": [
            {
               "boundingBox": "31,473,23,11",
              "text": "But"
             },
            {
              "boundingBox": "58,476,7,8",
              "text": "a"
            },
            {
               "boundingBox": "69,472,40,12",
              "text": "dream"
            },
            {
              "boundingBox": "113,472,41,12",
              "text": "within"
            },
            {
              "boundingBox": "158,476,7,8",
               "text": "a"
            },
            {
              "boundingBox": "169,472,47,12",
              "text": "dream?"
            }
          ]
        }
      ]
    }
  ]
}
  

Note that the image is split into an array of regions; each region contains an array of lines; and each line contains an array of words. This is done so that you can replace or block out one or more specific words, lines, or regions.

Below is a jQuery code snippet making a request to this service to perform OCR on images of text. You can download the full application at https://github.com/DavidGiard/CognitiveSvcsDemos.

    var language = $("#LanguageDropdown").val();
    var computerVisionKey = getKey() || "Copy your Subscription key here";
    var webSvcUrl = "https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/ocr";     
    webSvcUrl = webSvcUrl + "?language=" + language;
$.ajax({
    type: "POST",
    url: webSvcUrl,
    headers: { "Ocp-Apim-Subscription-Key": computerVisionKey },
    contentType: "application/json",
    data: '{ "Url": "' + url + '" }'
}).done(function (data) {
    outputDiv.text("");

    var regionsOfText = data.regions;
    for (var h = 0; h < regionsOfText.length; h++) {
        var linesOfText = data.regions[h].lines;
        for (var i = 0; i < linesOfText.length; i++) {
            var output = "";

            var thisLine = linesOfText[i];
            var words = thisLine.words;
            for (var j = 0; j < words.length; j++) {
                 var thisWord = words[j];
                output += thisWord.text;
                output += " ";

            }
            var newDiv = "

" + output + "
";
             outputDiv.append(newDiv);

        }
        outputDiv.append("


");
    }
               
}).fail(function (err) {
    $("#OutputDiv").text("ERROR!" + err.responseText);
});

You can find the full documentation – including an in-browser testing tool - for this API here.

Sending requests to the Cognitive Services OCR API makes it simple to convert a picture of text into text.  


It's difficult enough for humans to recognize emotions in the faces of other humans. Can a computer accomplish this task? It can if we train it to and if we give it enough examples of different faces with different emotions.

When we supply data to a computer with the objective of training that computer to recognize patterns and predict new data, we call that Machine Learning. And Microsoft has done a lot of Machine Learning with a lot of faces and a lot of data and they are exposing the results for you to use.

As I discussed in a previous article, Microsoft Cognitive Services includes a set of APIs that allow your applications to take advantage of Machine Learning in order to analyze, image, sound, video, and language.

The Cognitive Services Emotions API looks at photographs of people and determines the emotion of each person in the photo. Supported emotions are anger, contempt, disgust, fear, happiness, neutral, sadness, and surprise. Each emotion is assigned a score between 0 and 1 - higher numbers indicate a high confidence that this is the emotion expressed in the face. If a picture contains multiple faces, the emotion of each face is returned.

To get started, you will need an Azure account and a Cognitive Services Vision API key.

If you don't have an Azure account, you can get a free one at https://azure.microsoft.com/free/.

Once you have an Azure Account,  follow the instructions in this article to generate a Cognitive Services Computer Vision key.

To use this API, you simply have to make a POST request to the following URL:
https://[location].api.cognitive.microsoft.com/vision/v1.0/recognize

where [location] is the Azure location where you created your API key (above).

The HTTP header of the request should include the following:

Ocp-Apim-Subscription-Key.
This is the Cognitive Services Computer Vision key you generated above.

Content-Type

This tells the service how you will send the image. The options are:

  • application/json
  • application/octet-stream

If the image is accessible via a public URL, set the Content-Type to application/json and send JSON in the body of the HTTP request in the following format

{"url":"imageurl"}
where imageurl is a public URL pointing to the image. For example, to generate a thumbnail of this picture of a happy face and a not happy face,

TwoEmotions

submit the following JSON:

{"url":"/content/binary/Open-Live-Writer/Using-the-Cognitive-Services-Emotion-API_14A56/TwoEmotions_2.jpg"}

If you plan to send the image itself to the web service, set the content type to "application/octet-stream" and submit the binary image in the body of the HTTP request.

A full request looks something like this:

The full request looks something like:

POST https://westus.api.cognitive.microsoft.com/emotion/v1.0/recognize HTTP/1.1
Content-Type: application/json
Host: westus.api.cognitive.microsoft.com
Content-Length: 62
Ocp-Apim-Subscription-Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{ "url": "http://xxxx.com/xxxx.jpg" }

For example, passing a URL with a picture below of 3 attractive, smiling people

BrianAnnaDavid   

(found online at https://giard.smugmug.com/Tech-Community/SpartaHack-2016/i-4FPV9bf/0/X2/SpartaHack-068-X2.jpg)

returned the following data: 

[
  {
    "faceRectangle": {
      "height": 113,
       "left": 285,
      "top": 156,
      "width": 113
    },
    "scores": {
      "anger": 1.97831262E-09,
      "contempt": 9.096525E-05,
      "disgust": 3.86221245E-07,
      "fear": 4.26409547E-10,
      "happiness": 0.998336,
      "neutral": 0.00156954059,
      "sadness": 8.370223E-09,
      "surprise": 3.06117772E-06
    }
  },
  {
    "faceRectangle": {
       "height": 108,
      "left": 831,
      "top": 169,
      "width": 108
    },
    "scores": {
      "anger": 2.63808062E-07,
      "contempt": 5.387114E-08,
      "disgust": 1.3360991E-06,
      "fear": 1.407629E-10,
      "happiness": 0.9999967,
      "neutral": 1.63170478E-06,
      "sadness": 2.52861843E-09,
      "surprise": 1.91028926E-09
    }
  },
  {
     "faceRectangle": {
      "height": 100,
      "left": 591,
      "top": 168,
      "width": 100
    },
    "scores": {
      "anger": 3.24157673E-10,
      "contempt": 4.90155344E-06,
      "disgust": 6.54665473E-06,
      "fear": 1.73284559E-06,
      "happiness": 0.9999156,
      "neutral": 6.42121E-05,
      "sadness": 7.02297257E-06,
      "surprise": 5.53670576E-09
    }
  }
]   

A high value for the 3 happiness scores and the very low values for all the other scores suggest a very high degree of confidence that each person in this photo  happy. is

Here is the request in the popular HTTP analysis tool Fiddler [http://www.telerik.com/fiddler]:
Request

Em01-Fiddler-Request

Response:
Em02-Fiddler-Response 

Below is a C# code snippet making a request to this service to analyze the emotions of the people in an online photograph. You can download the full application at https://github.com/DavidGiard/CognitiveSvcsDemos.

string emotionApiKey = "XXXXXXXXXXXXXXXXXXXXXXX";
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", emotionApiKey);
    string uri = "https://westus.api.cognitive.microsoft.com/emotion/v1.0/recognize";
HttpResponseMessage response;
var json = "{'url': '" + imageUrl + "'}";
byte[] byteData = Encoding.UTF8.GetBytes(json);
using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

if (response.IsSuccessStatusCode)
{
    var data = await response.Content.ReadAsStringAsync();
}

You can find the full documentation – including an in-browser testing tool - for this API here.

Sending requests to the Cognitive Services Emotion API makes it simple to analyze the emotions of people in a photograph.  


Generating a thumbnail image from a larger image sounds easy – just shrink the dimensions of the original, right? But it becomes more complicated if the thumbnail image is a different shape than the original. For example, the original image may be rectangular but we need the new image to be a square. Or we may need to generate a portrait-oriented thumbnail from a landscape-oriented original image. In these cases, we will need to crop or distort the original image when we create the thumbnail. Distorting the image tends to look very bad; and when we crop an image, we want ensure that the primary subject of the image remains in the generated thumbnail. To do this, we need to identify the primary subject of the image. That's easy enough for a human observer to do, but a difficult thing for a computer to do. But if we want to automate this process, we will have to ask the computer to do exactly that.

This is where machine learning can help. By analyzing many images, Machine Learning can figure out what parts of a picture are likely to be the main subject. Once this is known, it becomes a simpler matter to crop the picture in such a way that the main subject remains in the generated thumbnail.

As I discussed in a previous article, Microsoft Cognitive Services includes a set of APIs that allow your applications to take advantage of Machine Learning in order to analyze, image, sound, video, and language.

The Cognitive Services Vision API uses Machine Learning so that you don't have to. It exposes a web service to return an intelligent thumbnail image from any picture.

You can see this in action here.

Scroll down the the section titled "Generate a thumbnail" to see the Thumbnail generator as shown in Figure 1. 

Th01
Figure 1

With this live, in-browser demo, you can either select an image from the gallery and view the generated thumbnails; or provide your own image - either from your local computer or from a public URL. The page uses the Thumbnail API to create thumbnails of 6 different dimensions.
 
For your own application, you can either call the REST Web Service directly or (for a .NET application) use a custom library. The library simplifies development by abstracting away HTTP calls via strongly-typed objects.

To get started, you will need an Azure account and a Cognitive Services Vision API key.

If you don't have an Azure account, you can get a free one at https://azure.microsoft.com/free/.

Once you have an Azure Account,  follow the instructions in this article to generate a Cognitive Services Computer Vision key.

     

To use this API, you simply have to make a POST request to the following URL:
https://[location].api.cognitive.microsoft.com/vision/v1.0/generateThumbnail?width=ww&height=hh&smartCropping=true

where [location] is the Azure location where you created your API key (above) and ww and hh are the desired width and height of the thumbnail to generate.

The “smartCropping” parameter tells the service to determine the main subject of the photo and to try keep it in the thumbnail while cropping.

The HTTP header of the request should include the following:

Ocp-Apim-Subscription-Key.     
The Cognitive Services Computer Vision key you generated above.

Content-Type

This tells the service how you will send the image. The options are:   

  • application/json    
  • application/octet-stream    
  • multipart/form-data

If the image is accessible via a public URL, set the Content-Type to application/json and send JSON in the body of the HTTP request in the following format

{"url":"imageurl"}
where imageurl is a public URL pointing to the image. For example, to generate a thumbnail of this picture of a skier, submit the following JSON:

{"url":"http://mezzotint.de/wp-content/uploads/2014/12/2013-skier-edge-01-Kopie.jpg"}

Man skiing  alps

If you plan to send the image itself to the web service, set the content type to either "application/octet-stream" or "multipart/form-data" and submit the binary image in the body of the HTTP request.

Here is a sample console application that uses the service to generate a thumbnail from a file on disc. You can download the full source code at
https://github.com/DavidGiard/CognitiveSvcsDemos

Note: You will need to create the folder "c:\test" to store the generated thumbnail.

   

             // TODO: Replace this value with your Computer Vision API Key
            string computerVisionKey = "XXXXXXXXXXXXXXXX"

            var client = new HttpClient();
            var queryString = HttpUtility.ParseQueryString(string.Empty);

            client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", computerVisionKey);

            queryString["width"] = "300";
            queryString["height"] = "300";
            queryString["smartCropping"] = "true";
            var uri = "https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/generateThumbnail?" + queryString;

            HttpResponseMessage response;

            string originalPicture = "/content/Giard/_DGInAppleton.png";
            var jsonBody = "{'url': '" + originalPicture + "'}";
            byte[] byteData = Encoding.UTF8.GetBytes(jsonBody);

            using (var content = new ByteArrayContent(byteData))
            {
                 content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response = await client.PostAsync(uri, content);
            }       
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                 // Write thumbnail to file
                var responseContent = await response.Content.ReadAsByteArrayAsync();
                 string folder = @"c:\test";
                string thumbnaileFullPath = string.Format("{0}\\thumbnailResult_{1:yyyMMddhhmmss}.jpg", folder, DateTime.Now);
                using (BinaryWriter binaryWrite = new BinaryWriter(new FileStream(thumbnaileFullPath, FileMode.Create, FileAccess.Write)))
                 {
                    binaryWrite.Write(responseContent);
                }
                // Show BEFORE and AFTER to user
                Process.Start(thumbnaileFullPath);
                 Process.Start(originalPicture);
                Console.WriteLine("Done! Thumbnail is at {0}!", thumbnaileFullPath);
            }
            else
            {
                Console.WriteLine("Error occurred. Thumbnail not created");
             }

        }            

The result is shown in Figure 2 below.
Th02Results
Figure 2

One thing to note. The Thumbnail API is part of the Computer Vision API. As of this writing, the free version of the Computer Vision API is limited to 5,000 transactions per month. If you want more than that, you will need to upgrade to the Standard version, which charges $1.50 per 1000 transactions.

But this should be plenty for you to learn this API for free and build and test your applications until you need to put them into production.
The code above can be found on GitHub.

You can find the full documentation – including an in-browser testing tool - for this API here.

The Cognitive Services Custom Vision API provides a simple way to generate thumbnail images from pictures.


As I discussed in a previous article, Microsoft Cognitive Services includes a set of APIs that allow your applications to take advantage of Machine Learning in order to analyze, image, sound, video, and language.

Your application uses Cognitive Services by calling one or more RESTful web services. These services require you to pass a key in the header of each HTTP call. You can generate this key from the Azure portal.

If you don't have an Azure account, you can get a free one at https://azure.microsoft.com/free/.

Once you have an Azure Account, navigate to the Azure Portal.

CsKey01-Portal
Figure 1

Here you can create a Cognitive Services API key. Click the button in the top left of the portal (Figure 2)

CsKey02-New
Figure 2

It’s worth noting that the “New” button caption sometimes changes to “Create a Resource” (Figure 2a)

CsKey02-CreateResourceButton
Figure 2a

From the flyout menu, select AI+Cognitive Services. A list of Cognitive Services displays. Select the service you want to call. For this demo,I will select Computer Vision API, as shown in Figure 3.

CsKey03-AICogServices
Figure 3

The Face API blade displays as shown in Figure 4.

CsKey04-ComputerVisionBlade
Figure 4

At the Name textbox, enter a name for this service account.

At the Subscription dropdown, select the Azure subscription to associate with this service.

At the Location dropdown, select the region in which you want to host this service. You should select a region close to those who will be consuming the service. Make note of the region you selected.

At the Pricing Tier dropdown, select the pricing tier you want to use. Currently, the choices are F0 (which is free, but limited to 20 calls per minute); and S1 (which is not free, but allows more calls.) Click the View full pricing details link to see how much S1 will cost.

At the Resource Group field, select or create an Azure Resource Group. Resource Groups allow you to logically group different Azure resources, so you can manage them together.

Click the [Create] button to create the account. The creation typically takes less than a minute and a message displays when the service is created, as shown in Figure 5.

CsKey05-GoToResourceButton
Figure 5

Click the [Go to resource] button to open a blade to configure the newly-created service. Alternatively, you can select "All Resources" on the left menu and search for your service by name. Either way, the service blade displays, as as shown in Figure 6.

CsKey06-ComputerVisionBlade
Figure 6

The important pieces of information in this blade are the Endpoint (on the Overview tab, Figure 7) and the Access Keys (on the Keys tab, as shown in Figure 8). Within this blade, you also have the opportunity to view log files and other tools to help troubleshoot your service. And you can set authorization and other restrictions to your service.

CsKey07-ComputerVisionOverview
Figure 7

CsKey08-ComputerVisionKeys
Figure 8

The process is almost identical when you create a key for any other Cognitive Service. The only difference is that you will select a different service set in the AI+Cognitive Services flyout.


Microsoft Cognitive Services is a set of APIs that take advantage of Machine Learning to provide developers with an easy way to analyze images, speech, language, and others.

If you have worked with or studied Machine Learning, you know that you can accomplish a lot, but that it requires a lot of computing power, a lot of time, and a lot of data. Since most of us have a limited amount of each of these, we can take advantage of the fact that Microsoft has data, time, and the computing power of Azure. They have used this power to analyze large data sets and expose the results via a set of web services, collectively known as Cognitive Services.

The APIs of Cognitive Services are divided into 5 broad categories: Vision, Speech, Language, Knowledge, and Search.

Vision APIs

The Vision APIs provide information about a given photograph or video. For example, several Vision APIs are capable of recognizing  faces in an image. One analyzes each face and deduces that person's emotion; another can compare 2 pictures and decide whether or not 2 photographs are the same person; a third guesses the age of each person in a photo.

Speech APIs

The Speech APIs can convert speech to text or text to speech. It can also recognize the voice of a given speaker (You might use this to authenticate users, for example) and infer the intent of the speaker from his words and tone. The Translator Speech API supports translations between 10 different spoken languages.

Language

The Language APIs include a variety of services. A spell checker is smart enough to recognize common proper names and homonyms. And the Translator Text API can detect the language in which a text is written and translate that text into another language. The Text Analytics API analyzes a document for the sentiment expressed, returning a score based on how positive or negative is the wording and tone of the document. The most interesting API in this group is the Language Understanding Intelligence Service (LUIS) that allows you to build custom language models so that your application can understand questions and statements from your users in a variety of formats.

Knowledge

Knowledge includes a variety of APIs - from customer recommendations to smart querying and information about the context of text. Many of these services take advantage of natural language processing. As of this writing, all of these services are in preview.

Search

The Search APIs allow you to retrieve Bing search results with a single web service call.

You can use these APIs. To get started, you need an Azure account. You can get a free Azure trial at https://azure.microsoft.com/.

Each API offers a free option that restricts the number and/or frequency of calls, but you can break through that boundary for a charge.  Because they are hosted in Azure, the paid services can scale out to meet increased demand.

You call most of these APIs by passing and receiving JSON to a RESTful web service. Some of the more complex services offer configuration and setup beforehand.

These APIs are capable of analyzing pictures, text, and speech because each service draws on the knowledge learned from parsing countless photos, documents, etc. beforehand.
 
You can find documentation, sample code, and even a place to try out each API live in your browser at https://azure.microsoft.com/en-us/services/cognitive-services/

A couple of fun applications of Cognitive Services are how-old.net (which guesses the ages of people in photographs) and what-dog.net (which identifies the breed of dog in a photo).

Below is a screenshot from the Azure documentation page, listing the sets of services. But keep checking back, because this list grows and each set contains one or more services.

List of Cognitive Services
 
Sign up today and start building apps. It’s fun, it's useful, and it’s free!


Rob Reynolds on Chocolatey

Comments [0]

I have been recording my online TV show - Technology and Friends - for 9 years. I recently passed episode #500.

The show has evolved over the years and so has the recording equipment I use.

Below is a description of the hardware I use to record Technology and Friends.

Camera: Canon EOS6D

CameraThis is the second Canon SLR I’ve purchased. My EOS 30D lasted over 10 years, so I returned to a similar, but updated model when it finally began to fail. The EOS 6D is primarily a still camera, but it can record up to 30 minutes of high-resolution video. The image quality is outstanding, particularly with the 24-105mm Canon lens I bought with it. This setup is overkill (read: "expensive") for a show that most people view in a browser, but I also use this camera for still photography and I have been happy with the results. The main downside for video is the 30-minute limit. After this time, someone needs to re-start the recording.

Audio Recorder: Xoom H6 Handy Recorder

AudioRecorderI bought a Xoom recorder a few years ago on the recommendation of Carl Franklin, who is the co-host and the audio expert of the excellent .NET Rocks podcast. It served me well for years, so I bought the H6 when it was time to replace it. This device contains 2 built-in microphones, but I almost always plug in 2 external microphones, so I can get closer to a speakers mouth. I can plug in up to 4 external microphones. Using these microphones eliminates most of the background noise, allowing me to record in crowded areas. Each microphone can record to a separate audio file, which is convenient if one speaker is much louder than another.

Microphones: Shure SM58

MicrophonesI went with Shure based on popularity and Amazon reviews. I bought these mid-level models. I have been happy with the results. I strongly recommend external microphones (either lapel or handheld) when recording audio. My show is much better since I began using them. Switching to a separate microphone and the resulting increase in audio quality is probably the technical change resulting in the single biggest jump in quality for my show.
 


Tripod: Vanguard Lite1

TripodThis is a cheap tripod, but it has lasted me for years. I have a larger tripod, but seldom use it because I can throw the vanguard is small enough to keep in a backpack, carry on a plane, and carry around a conference. I also like the fact that I can set it on a tabletop, which is what I usually do. It is not quite tall enough to stand on the ground and hold the camera as high as the face of a standing adult.


Me and Roy Roy Ayers is 77 years old and stutters when he talks. But not when he sings. And definitely not when he plays the vibraphone. And play he did last night in front of a packed house at The Promontory in Hyde Park.

Ayers mixed a few ballads with the jazz-funk that he helped define. Backed by a band consisting of bass, drums, keyboard, and another vocalist, Ayers played for about 90 minutes, drawing on his 99 albums with such songs as "Red, Black & Green", "Don't Stop the Feeling", and his interpretation of Sam Cooke's "You Send Me".

The keyboardist was the best of the bunch, coaxing a variety of sounds from his instrument during his many solos. I wondered why the stage setup hid so much of him from the audience's view.

And then there was Roy and his vibraphone. Ayers still sounds great when he does his thing with his vibes.

Also Me and RoyI bought a ticket at the door and had to stand in the back with some folks who decided it was ok to engage in loud conversation at the concert. But I had a chance to shake the hand of Mr. Ayers after the show and tell him how much I enjoyed his music.

And to wish him luck on his next 99 albums.


"Mirror Dance" by Lois McMaster Bujold is the sequel to "Brothers In Arms", the novel that introduced Miles Vorkosigan's clone / brother Mark.

mirror_danceFollowing Miles's rescue of Mark in the previous novel, the brothers return to Miles's home planet of Barrayar, where Mark decides to launch a rescue mission to liberate clones who are intended to be used as replacement parts for their genetic donors. Miles follows and is gravely wounded in the ensuing battle. His body is cryogenically frozen and then disappears. Mark returns to Barrayar to deliver the news to their parents - Lord Aral and Lady Cordelia. Arel and Cordelia  accept Mark as their son and a potential heir to the Vorkosigan line. Ultimately, Mark launches another rescue mission, this one to find and save Miles, who has been revived by scientists on an enemy planet.

This is one of Bujold's strongest novels. She not only tells a complex story, but she dives further into the emotions of her characters - particularly the clone Mark.

The definition of humanity and the rights that go with it are common themes of Bujold's books and this one delves into it very well, if a little heavy-handed. Interwoven with this general question is Mark’s personal struggle to define his own identity. He desperately wants to define himself outside of just the clone of a heroic Lord. But, his struggle to do so often leads to failure. Others help him with the struggle. He was raised to assassinate Miles's father, but ends up being accepted by his potential victim and his new family.




BrothersInArmsFor years, Miles has been leading a double life - he was born Lord Miles Vorkosigan who became a lieutenant in the army of the Barryaran empire; but he sometimes assumes the role of Admiral Naismith, leader of the  Dendarii Free Mercenary Fleet.

One day, Miles is forced to appear on the same planet as both of his persona on the same day. Fearing his cover will be blown, he invents a story that Naismith is actually Miles's clone.

Shortly afterward, Miles discovers that he actually does have a clone and that this clone is being used by his enemies in a plot to assasinate Miles.

The book is a good adventure story. It advances the relationship between Miles and Elli (his bodyguard / lover); and it addresses a glaring plot problem - Miles disguises himself as a mercenary Admiral despite his unique physique. It also takes place on future Earth, which is a bonus for those of us who call Earth home today.



November 2017 Gratitudes

Comments [0]

12/3
Today I am grateful to attend DataSciConf in Atlanta for the first time.

12/2
Today I am grateful for dinner last night with Shawn and Resa.

12/1
Today I am grateful to see an exciting Hawks-Cavs game with Dave at Philips Arena last night.

11/30
Today I am grateful for:
-Arriving safely in Atlanta after some delays.
-The Data Sci conference speaker dinner last night

11/29
Today I am grateful to the Greater Chicago Food Depository for letting me help yesterday.

11/28
Today I am grateful to Lisa and Betsy for taking over the Midwest Geeks call, after my 4 years facilitating it.

11/27
Today I am grateful for the public library.

11/26
Today I am grateful for a weekend in Michigan visiting friends and family.

11/25
Today I am grateful to Desi and Ondrej for a home-cooked meal and a place to stay last night.

11/24
Today I am grateful to celebrate Thanksgiving dinner with family in Michigan.

11/23
Today I am grateful that most of my family lives within driving distance.

11/22
Today I am grateful to see Mark Colby in concert at the Jazz Showcase last night.

11/21
Today I am grateful for the cabinets I cleaned out last night and all the crap I threw away.

11/20
Today I am grateful for the man who watched my car at the airport terminal yesterday while I ran in to check a bag.

11/19
Today I am grateful to deliver the keynote at GangConf yesterday and to remain a part of #MIGANG after all these years.

11/18
Today I am grateful for:
-Attending a home Raptors game for the first time;
-My first visit to Canada in 10 years

11/17
Today I am grateful for:
-My first visit to the University of Toronto
-An exciting overtime NHL game at Air Canada Arena
-My first time attending a Maple Leafs home game.

11/16
Today I am grateful for my first visit to the University of Waterloo.

11/15
Today I am grateful for my first visit to the Massachusetts Institute of Technology.

11/14
Today I am grateful to arrive safely in Boston on a difficult travel day.

11/13
Today I am grateful for:
-a walk around downtown Princeton, NJ yesterday afternoon
-a tour of Princeton University by Mihaela Friday afternoon

11/12
Today I am grateful to get to bed early last night.

11/11
Today I am grateful for my first visit to Princeton, NJ and Princeton University.

11/10
Today I am grateful to attend an exciting Philadelphia Flyers game last night at the Wells Fargo Arena with Jeffrey.

11/9
Today I am grateful to Sarah for making me look good at UIUC yesterday.

11/8
Today I am grateful to the Uber driver who stopped by my home to drop off the lens cap I left in his car last week.

11/7
Today I am grateful to speak at PyData Chicago for the first time.

11/6
Today I am grateful that the weather here is still nice enough that I can walk to church.



Outlander, the first novel by American author Diana Gabaldon, was originally published in 1991. It has since inspired 7 sequels (so far), a TV series, and a graphic novel.

OutlanderThe story focuses on Claire, a World War II combat nurse. The war kept Claire and her husband Frank apart; so, when it ended, they traveled to Inverness, Scotland for a second honeymoon and to allow Frank to research his ancestors.

While in Scotland, Claire encounters an ancient Druid shrine that magically transports her to the mid-18th century. Almost immediately after entering the past, Claire is attacked by the sadistic British Captain Jack Randall. It turns out that Randall is the direct ancestor of Claire's 20th century husband. She is rescued by Scottish clansmen and caught in the struggle between the English army and the Scottish clans.

Although often classified as a science fiction novel (I first learned of Outlander on NPR's Top 100 Science Fiction & Fantasy Books, this book is primarily an historical romance. The time travel incident serves mostly as a MacGuffin to thrust together Claire and Jamie.

Despite Claire's 20th century marriage, she falls in love with Jamie Fraser, the handsome, rugged Scottish warrior. Their marriage is initial one of convenience (Claire can escape English arrest by becoming a Scottish citizen), but a passion soon ignites between the two and the subsequent sex scenes are frequent and racy enough to make a Scotsman blush.

Outlander is also an adventure story. Jamie and Claire are pursued across Scotland by the English army and the vengeful Captain Randall. Claire is captured and rescued, and Frank is captured and rescued, and they travel and fight the English and have sex with each other and fight each other and have sex with the English and travel some more.

Outlander is not for everyone. Some readers will take issue with the patriarchal nature of 18th century marriages - particularly a scene where Jamie beats his wife for disobeying him and Claire is quick to forgive him. Others may be turned off by a prolonged description of male-on-male rape and torture near the end of the book.

But if you can get past these, it is a pretty good story. And enough readers think so that Gabaldon continues to extend this series today.


HomelandDrizzt Do'Urden was born into the underworld of Mgnzoberranzan, home of The Drow or Dark Elves. The city is ruled by the tyrannical Matrons, who worship the malevolent spider god Lolth. Theirs is a world in which violence and treachery are praised and rewarded, while empathy and sympathy are perceived as weaknesses to be severely punished. Mgnzoberranzan is divided into Great Houses, that often clash violently with one another to improve their standing within this city's hierarchy.

Drizzt is the most gifted warrior of his people. He is trained by the great Weapon Master Zaknafein and he surpasses all his classmates at the Academy.

But Drizzt is unlucky enough to be born with a conscience in this sadistic, society. He questions the ethics of the Menzoberranzan society and their worship of the malevolent spider-god Lolth.

Drizzt joins in the drow attacks against his people's enemies. His fighting prowess increases his reputation, but he begins to see that his family and people have been dishonest about the character and motivations of their enemies.

Homeland is the first book in R. A. Salvatore's Dark Elf Trilogy, which is chronologically the first trilogy of his Legend of Drizzt series. These series and many of Salvatore's other books take place in the Forgotten Realms universe, made popular by the Dungeons and Dragons fantasy role-playing game.

The novel is an adventure story and Drizzt is never certain who (if anyone) is his ally. He hopes, but does not know if he can count on Zaknafein and the pan-dimensional panther Guenhwyvar as allies. Each of the great houses uses deception to plot against rival houses in their quest for revenge and power in this dysfunctional world.

Homeland explores the conflict between personal principles and our natural desire to belong to a family and social order. Drizzt's conflicts are extreme (he is good, and his family and people are evil), but we all suffer this same internal battle at times.

The characters don't have a lot of depth and the writing is a bit heavy handed at times. But the story is good fun. And I enjoyed it.


Oren Eini on RavenDB

Comments [0]

For Callie

Comments [0]

Callie in 1998Callie's childhood was tougher than most. She was abandoned by her parents at a young age and raised by her aunt and uncle, which is when I met her. They lived next door to us and befriended my boys, who were a few years younger than her and her brother.

As an adult, she tried to help her younger brother, who was in and out of trouble much of his life and died young. She was a single mother. She was as a teacher and social worker. She had a beautiful smile.

She died last week of a brain aneurism.

She was 32 years old.

She will be buried on Saturday.

Callie in 2017



Borders of Infinity by Lois McMaster Bujold is a collection of 3 previously published novellas: Mountains of Mourning, Labyrinth, and The Borders of Infinity. All 3 feature Bujold's hero Miles Vorkosigan, the handicapped royal soldier from the planet Barayar.

In Mountains of Mourning, Miles travels to the back country of Barayar to investigate the murder of a baby, who was killed because she was born with a cleft pallet.

In Labyrinth, Miles attempts to recruit a geneticist to the Barayaran cause, but ends up bonding with a genetically-engineered female super soldier.

In The Borders of Infinity, Miles is taken prisoner by the Cetagandans. He hopes to rescue a prisoner, but ends up planning a massive prison break.

When I read the first 2 stories, I was optimistic that they would be joined by a common theme - Miles's protection of others who were punished for being handicapped at birth. But the third story did not continue this theme. So, the 3 stories are tied together only by a brief narration in which Miles relates his activity to a superior officer.

As a result, this is little more than an omnibus of loosely related stories, each of which is good, but not great.


TheLasrtUnicorn

At first, the unicorn was happy, living alone in a magical wood. Her magic kept her eternally young and kept the wood eternally in spring.

But one day, she overheard 2 hunters saying that all unicorns had gone from this world. Fearing she might be the last, the unicorn set out on a journey to find others of her kind.

Along the way, she is captured by a witch for display in her circus; then, rescued by a third-rate wizard, who accompanies her on her journey.

Ultimately, she makes her way to a kingdom guarded by the mystical Red Bull, that is rumoured to have captured all the other unicorns.

With The Last Unicorn, Peter S. Beagle weaves a wonderful fairy tale about the adventures of a unicorn on a quest to find others and to find herself. It is a story of adventure and it is a story of companionship and loyalty.

But mostly, it is the telling of the story that sets it apart. Beagle's prose is almost like poetry. The beauty of the unicorn is reflected in the beauty of his words.

This book was a joy to read - from start to finish.


PerdidoStreetStationPerdido Street Station is an enormous train station in the city of New Crobuzon in the world of Bas-Lag. It is also the title of China Miéville's novel about the the station, the city, and the world.

The problems of industrialized societies in our world are magnified a hundred times in the city state of New Crobuzon: Pollution, Poverty, Political corruption, an Inequitable distribution of wealth and power, and Racial division make this place a miserable home for nearly all who dwell in it.

The races of Bas-Lag are not simply people of different skin tones and nose shapes; they are a bizarre assortment of creatures - mostly humanoid, but some not. We see bird-men (Garuda), intelligent plants (Cactacae), aquatic humanoids (Grindylow), parasites shaped like disembodied hands that grasp the throats of their victims (Handlingers), humans with the head of a beetle (Khepri), and sentient machines (Constructs), among others.

A common form of punishment in New Crobuzon is to surgically alter people by attaching mechanical or organic body parts to their bodies, creating a separate race of "Remades" and further increasing the collection of creatures found in this world.

Creatures from other dimensions also sometimes visit Bas-Lag, such as The Weaver a giant spider-like creature, who seeks to add his own version of order to the world. In this novel, Hell is a tangible place that sends an official Ambassador to New Crobuzon.

Isaac is a scientist living and working in New Crobuzon. He is in love with the Lin - a Khepri artist who is estranged from her own people. One day the Garuda Yagharek approaches Isaac asking him to restore to him the power of flight. Yagharek's wings were removed by his tribe as punishment for an unidentified crime. Isaac accepts and begins by studying the biology of hundreds of flying creatures. His studies inadvertently unleash the Slake-Moths - deadly, interdimensional creatures with the power to hypnotize their prey before devouring their consciousness.

The slake-moths terrorize the city, leaving behind mindless shells of people wherever they attack. The government and numerous vigilante groups are unable to stop the slake-moths, so Isaac - feeling responsible - organizes a group of warriors to hunt them down and destroy them.

This world is powered by magic and by technology. But it's an old technology. Blimps are the most common form of air transportation and computers are programmed via punch cards. These punch-card-programs are powerful enough to make some computers self-aware.

I loved the moral ambiguity of this story. Our heroes often must make difficult choices - such as sacrificing the lives of innocent bystanders - in an effort to stop the monsters terrorizing the city.

I loved the complexity of the plot. Most storylines are not resolved until the very end and many are not happy resolutions.

I loved Miéville's attention to detail. We can see the massive bulk of the weaver as he fades into our dimension; we feel the terror inspired by the slake-moths.

The reader experiences the feeling of dread that hangs over the protagonists. Miéville gives us a real sense of the despair felt by so many in this awful world he created. Citizens live in a police state, controlled by a secret militia, controlled by the mayor and a few powerful businessmen.

Perdido Street Station is a fantasy story, a steampunk story, a horror story, a monster story, an adventure story, a detective story, a cyberpunk story, and a love story. Some have described it as Weird Fantasy in the tradition of H.P. Lovecraft and some of the pulp writers of the 1930s.

However, you choose to classify it, Perdido Street Station is one of the most imaginative stories I've read in years.



October 2017 Gratitudes

Comments [0]

11/5
Today I am grateful to see my nephew Dylan play ice hockey in Glenview, IL yesterday.

11/4
Today I am grateful that so many people traveled so far to come to the Community Connections event yesterday.

11/3
Today I am grateful to visit the Chicago Museum of Science and Industry yesterday with Ondrej and Gaines.

11/2
Today I am grateful that I accomplished everything I wanted to accomplish yesterday.

11/1
Today I am grateful that I actually lost weight while in Uruguay, despite all the beef that I ate.

10/31
Today I am grateful for my first visit to South America, to Fabian for inviting me, and to Rachel for recommending me.

10/30
Today I am grateful for my first visit to Buenos Aires.

10/29
Today I am grateful for a private tour around Montevideo by the #NETConfUY organizers.

10/28
Today I am grateful to attend and speak at .NET Conf UY for the first time.

10/27
Today I am grateful for the speaker dinner last night, featuring carne asada.

10/26
Today I am grateful for a late-night walk along the Rio de la Plata last night.

10/25
Today I am grateful for a walk around downtown Montevideo last night.

10/24
Today I am grateful to arrive safely in Uruguay.

10/23
Today I am grateful for a good day at the gym yesterday.

10/22
Today I am grateful to attend my first Chicago Wolves hockey game last night.

10/21
Today I am grateful I was able to consolidate my Azure web apps and delete a bunch of costly resources yesterday.

10/20
Today I am grateful for good news from the doctor yesterday.

10/19
Today I am grateful to hang out in downtown St. Louis yesterday with Ondrej, Brian, Gaines, and Mary.

10/18
Today I am grateful to speak again at the #DevUp conference.

10/17
Today I am grateful to attend the Red Shirt Tour in Chicago yesterday and learn more about Azure.

10/16
Today I am grateful
-to see an exciting Falcons-Dolphins game yesterday at my first visit to Mercedes Benz Stadium;
-to Tim for picking me up at the airport last night.

10/15
Today I am grateful to help Jason and Claire celebrate their wedding yesterday.

10/14
Today I am grateful for 4 years at Microsoft and all that I have learned here and all the people I've met and all the places I've gone because of this job.

10/13
Today I am grateful to David for a ticket to see Paul Weller in concert last night at the House of Blues.

10/12
Today I am grateful I was able to recover data from my laptop after it died yesterday.

10/11
Today I am grateful for a chance to teach at DePaul last night.

10/10
Today I am grateful for dinner last night with my new teammate Christine while she was in Chicago.

10/9
Today I am grateful for dinner with Emilija and Larissa last night.

10/8
Today I am grateful for
-spending the day with my son, helping him move;
-the 8th football victory over um in the last 10 years.

10/7
Today I am grateful for:
-A chance to work with Julie for the first time since our days on the INETA board.
-Seeing The Church in concert last night at Park West.

10/6
Today I am grateful to hang out with J. yesterday.

10/5
Today I am grateful to stream music online.

10/4
Today I am grateful to the Building Maintenance staff for fixing a bunch of stuff in my apartment yesterday.

10/3
Today I am grateful to those who find what I do useful and tell me so.

10/2
Today I am grateful for:
-the company of Tim these past few months
-the opportunity to try 2 new cuisines for the first time yesterday.


I always like to prepare for a trip to a new country, so when I was invited to speak at .NET Conf UY in Montevideo, Uruguay, I decided I should learn some Spanish. I taught myself how to say "Buenos Dias" and "Adios". Unfortunately, I neglected to learn the many things I should talk about between these two phrases. But it worked out. Most of the Uruguayans with whom I interacted spoke at least some English and the conference provided real-time translation of all presentations, so that I could understand the Spanish speakers, and the audience could understand me.

Arrival

I arrived Tuesday morning 2 days early. Originally, I thought I might deliver a workshop, but my first session was not scheduled until Thursday afternoon. It was an all-night flight from Miami to Montevideo. Fabian - one of the conference organizers - picked me up at the airport. He recognized me from my photograph, despite my disheveled appearance. Exhausted from the flight, I checked into the hotel and slept for a few hours; then spent a few hours catching up on work for my day job.

I20171025_161849_HDRn the evening, I walked around the hotel neighborhood. I hoped to find some dinner, but I discovered that Uruguayans eat later than Americans and most restaurants do not serve dinner until at least 7PM. I settled for a salad in a nearby hotel restaurant.

I passed the Uruguayan World Trade Center - a cluster of office and retail buildings, tallest of which is about 40 stories. Then I made my way to the Río de la Plata - at 120km, the widest river in the world.

I did not realize until Wednesday morning, that 2 hotel reservations had been made for me - one by me and one by the conference organizers. I went to the Sheraton to cancel my reservation. They allowed me to cancel the week, but charged me for 2 (expensive) nights, so I decided to spend Wednesday night at the Sheraton. It was a nicer hotel, and I had already paid for it.

In the afternoon and evening, I walked around a different neighborhood and a different part of the river, exploring parks and side streets and beaches. Nearly the entire riverfront of Montevideo is public space, featuring beaches and parks, so one can walk for miles along the shore. I had heard of the fondness South Americans have for beef, so I ordered a filet in a nice restaurant.

Late at night, I stopped at a beachside tavern to try a Uruguayan wine. The waitress spoke no English, and I speak almost no Spanish, but she managed to recommend a good local wine as we typed our conversation into my phone and let Google translate for us.

.NET Conf UY

20171027_103507_HDRThe breakout sessions of .NET Conf UY took place Thursday and Friday. I delivered 2 sessions - "Adding Image and Voice Intelligence to Your Apps with Microsoft Cognitive Services" and "Big Data Solutions in Azure". The first presentation went very well, and many attendees approached me afterward with session. A demo failed in my second presentation, but I managed to recover.

I met many new people at this conference. My teammate Shahed flew down from Virginia and I had corresponded briefly with Fabian, but I knew no other speaker, organizer or attendee before I arrived.

I recorded 2 interviews for my show, including one with keynote speaker Carolina Banales. The conference hired a video crew, and they interviewed me on camera.

20171026_210522_HDRThursday evening, Kiezen - one of the conference's main sponsors - hosted a speaker dinner at their new offices. A brick grill graces the roof of this office and we were treated to Uruguayan asade, which is meat grilled over a wood fire. I ate too much.

Friday evening featured an attendee party high above downtown Montevideo. This gave me the opportunity to get to know a lot of new people. The language barrier sometimes slowed communication, but I found everyone I met to be very engaging.

Tour of Montevideo

The day after the conference, the organizers reserved a bus and took us around Montevideo to show some of the major sites. Highlights included:

Estadio Centenario, where the first World Cup tournament was held (and won by Uruguay)

20171028_221708The Montevideo sign, that spells the city name in letters 5 feet tall. The sign overlooks one of the city's harbors and is a favourite spot for photographs.

The Fortezza General Artigas, which sits atop a hill overlooking the city from across Montevideo Bay. The fort is primarily dedicated to General Jose Artigas, who led the Uruguayans in their battle for independence in the early 19th century; but it is also a museum of military history. As a bonus, it offers a spectacular view of the Montevideo skyline.

We finished with an asade lunch at an outdoor cafe in the Old City. A Brazilian band stopped by to serenade us while we ate. From there, we went to the Independence Plaza, where a parade was about to start.

Buenos Aries

20171029_131243I spent Sunday in Buenos Aires, Argentina, which is only 200 km from Montevideo. There are several ways to make this journey. I chose to travel by bus from Montevideo to Colonia, Uruguay to see some of the Uruguayan countryside, which is mostly flat farmland with a few rivers and isolated woodlands. Buenos Aires is a short ferry ride from Colonia.

I was only in Buenos Aires for a few hours, but I managed to visit Casa Rosado, where Eva Perrone famously addressed her people from a balcony; Iglesia de St. Ignatius, the oldest church in the city; and the towering Obelisca de Buenos Aires that commemorates the city's 400th birthday. Lunch at Cafe Tortoni - the oldest cafe in Buenos Aires - was very good. In between, I walked through numerous public parks, side streets, and riverfronts.

Buenos Aires is a beautiful city. The architecture reminds me of a modern European city. I hope to return when I have more time.

Final Day

20171026_111236My flight home was scheduled for Monday evening and I made no plans on Monday. After sleeping in, I enjoyed a leisurely lunch and checked out of my hotel. There is a small zoo just 2 blocks from my hotel, so I decided to spend some time there. Sadly, the zoo is closed on Mondays, as was the planetarium next door. Instead, I walked to a section of the riverfront I had not yet visited, took some photos, and stopped at a small cafe for a cappuccino and a light dinner.

Fabian was kind enough to pick me up and drive me to the airport.

A Few Facts

Here are some things I learned about Montevideo and Uruguay this past week.

  • Uruguay is the second smallest country in South America.
  • Over half the country's population lives in the Montevideo area.
  • There are no giant skyscrapers in Montevideo. The tallest building is 35 stories - not much bigger than my apartment building in Chicago.
  • I cannot verify this, but I was told that Montevideo comes from the following words:
         "Monte", meaning "small hill"
         "VI" for the Roman Numeral
         "deo", which is short for "de Este a Ouest", which means "From East to West"
    In other words, the city sits on the sixth hill from east to west.
  • Many of the city's sidewalks are made of bricks, which is probably why so many Montevideo sidewalks are broken.
  • Uber is available in Uruguay. I never had to wait more than 5 minutes and never paid more than $7US for a ride.

I am grateful I had the opportunity to come to South America and see the sights and meet so many kind people.  I enjoyed the experience, and I hope to return. And I even learned a few extra Spanish words.

Gracias, Montevideo.

Hasta la vista.




Ethan of Athos is one of the few books set in Lois McMaster Bujold’s universe of Miles Vorkosigan that does not feature an appearance by Miles or any member of his family.

The story begins on Athos - a planet populated solely by males, because they banned females generations ago. The men of Athos reproduce by importing ovaries and cultivating babies in birth chambers. Dr. Ethan Urquhart examines a new shipment of ovaries and discovers that they are useless - some damaged and some from animals.

Much to Ethan's chagrin, the Athos government assigns him to travel off planet and find out what happened to their original shipment. This distresses Ethan, who has been conditioned all his life to be repulsed at the thought of women.

Of course, Ethan finds himself the target of a murder attempt and he is rescued by a female assassin - Elli Quinn. Together, Ethan and Quinn track down the reason the shipment was stolen and replaced.

The story has action and intrigue, but also some messages about culture. Athos holds deep prejudices against women; and others in the galaxy hold prejudices against Athos for their homosexual lifestyles. To succeed, Ethan must overcome his prejudices and work with Quinn.

While not one of Bujold's best novels, I still enjoyed Ethan of Athos.



CetagandaMile Vorkosigan and his cousin Ivan of the Barrayar Empire attends the funeral of the empress of the rival Cetagandan Empire.

Shortly after landing, they are attacked by a Cetagandan servant and wrestle away a mysterious artifact. When the servant turns up dead shortly afterward, Miles and Ivan must figure out who is behind the murder, the theft of the artifact, why is the artifact so valuable, and the political plot they ultimately uncover.

Like all of Lois McMaster Bujold's novels, Cetaganda" combines action, political intrigue, and character development.  This one is primarily a detective story with Miles and Ivan uncovering clues that help them uncover the answers to the questions above.

This novel introduces the Cetagandans and provides details about their culture. It was written later than other stories that feature this race/empire and I'm told it helps to better understand their motivations.

Bujold has a talent for building rich characters and adding layers in each novel. In this story, we get a deeper look inside the mind of the carefree, womanizing Ivan and see the reaction of Miles, who is less smooth and less attractive due to his diminished size and birth defects. It's easy to cheer for Miles the underdog, despite the privileges being born to royalty.


Miles Vorkosigan is young and intelligent, but deformed and undersized, thanks to a failed assassination attempt on his mother a few months before his birth. He has the added pressure of being the son of the legendary Lord Admiral Aral Vorkosigan - one of the great military strategists of the Barrayaran Empire.

After graduating from Barrayaran Service Academy, Miles enters military service - first on an isolated frozen island under a corrupt commander, where he is falsely accused of treason. After clearing his name, he is given a security assignment far from Barrayar, where he is again framed - this time for murder. While trying to escape, he runs into the Emperor Gregor - only slightly older than Miles - who has run away to escape his responsibilities. Together, Miles and Gregor must prevent Cavilo - a femme fatal, who will kill, betray, and/or seduce anyone to gain power. She seeks to throw the empire into chaos and make herself empress. Amazingly, she has aligned herself with Miles's old corrupt commanding officer. Miles seeks the help of the Dendarii mercenaries with whom he worked under the alias of Admiral Naismith in The Warrior's Apprentice

The Vor Game advances the story of young Miles, who is an unlikely hero, thanks to his physical handicaps. Bujold establishes Miles's issues with following authority, which gets him into trouble; but also with his headstrong ways, which sometimes gets him out of trouble. We also get our first look into what makes Emperor Gregor tick.


Bujold does a very good job of mixing action, political intrigue, and character development into her stories. There are a few too many coincidences, as Miles keeps running into people from his past while at the far edge of the galaxy; but one can forgive this because the story is engaging, and the coincidences help to move it forward.



SwordOfShannarShea Ohmsford was living a quiet life, running a farm with his brother Flick. Shea knew he was adopted, but when the tall stranger Allanon shows up, he learns that he is half-elf and the last living member of the legendary Shannara family.

Allanon convinces the brother that their land is danger from The Warlock Lord - an evil wizard, who seeks the power of the legendary sword of Shannara; so, the three of them set out on a quest to find the sword. Along the way, they are joined by men and elves and attacked by gnomes, trolls, and black flying monsters known as "skull bearers". They are separated during their journey, but continue their mission to thwart the Warlock Lord.

This is the story of The Sword of Shannara by Terry Brooks. If it sounds familiar, it is because Brooks acknowledges J.R.R. Tolkien as one of his influences.

Comparison's with the Lord of the Rings are inevitable: A disparate group, consisting of men, elves, and dwarves travel across a mystical land to seek a powerful magic relic, preventing the evil wizard from acquiring it first. There is even a crazy gnome with a startling resemblance to Gollum.

If you can get past Brooks's obvious "inspiration" for his plot, he does tell a pretty good story. The narrative is more traditional than Tolkien's and more appropriate for the simpler story. I enjoyed it.


TheChurch02This week, I went to The Church on Friday night.

In this context, The Church is the Australian rock band and they were performing at Park West in Lincoln Park, Chicago.

It turns out that The Church has had a long career beyond their 1988 "Starfish" album - the CD my brother gave me decades ago that I played repeatedly in the 80s and 90s. "Starfish" was their most popular album, but they were almost a dozen songs into their set before playing the first song from this album - "North South East & West".

TheChurch01They filled the night with music from the early 1980s (lead singer Steve Kilbey joked that he was 2 years old when he wrote one of the songs) and from their latest album ("Man Woman Life Death Infinity", which was released today). In almost 4 decades, the band has released dozens of albums and they drew on many of them tonight They alternated between straight-ahead post-punk rockers and the ethereal music for which they are most well-known.

TheChurch03For me, the high point was hearing "Under the Milky Way". It was like a visit from an old friend and the emotion of the harmonies and acoustic guitar still speak to me after all these years.

My first visit to Park West was an enjoyable one. It was a good night to visit The Church. ie



The following articles walk the user through creating an ASP.NET application; storing source control history in a Visual Studio Team Services project Git repository; and automatically deploying to an Azure web app whenever code changes are pushed to the repository.

Creating a Team Project in Azure

Creating an ASP.NET Web Project and Storing code in a VSTS Git Repository

Configuring Automatic Deployment from VSTS to an Azure Web App


This is Part 3 in a series of articles about integrating VSTS, Azure Web Apps, ASP.NET applications, and Visual Studio.

In previous articles, I showed you how to create a VSTS Team Account and Team Project linked to Azure  and how to create an ASP.NET Web application and link this to your VSTS team project in order to store the project code in the Team Version Control Repository.

In this article, I will show you how to automatically deploy code from your VSTS Team Project repository to an Azure Web App every time you push code changes to that repository.

This configuration is done in the Azure portal.

Log into your Azure account and navigate to the portal by clicking the PORTAL link at the top right, as shown in Fig. 1.

VSTSp3-01-AzurePortalLink
Fig. 1

From the Azure portal, select

New | Web + Mobile | Web App

as shown in Fig. 2.

VSTSp3-02-NewWebApp
Fig. 2

The Create Web App blade displays, as shown in Fig. 3.

VSTSp3-03-CreateWebAppBlade
Fig. 3

At the App Name field, enter a name for your app. This must be unique among Azure App Services. Although you can assign a custom domain to this later, the default URL will be

http://xxxx.azurewebsites.net

where xxxx is the name you assigned to this Web App.

If you navigate to this URL (or click the hyperlink in the Overview tab), you will see a default Azure We App page.

At the Resource Group field, select "Create New" and enter a name for your resource group.

At the "OS" field, select the operating system on which you want to deploy your Web App.

Click the [Create] button to create your Web App. This usually takes less than a minute. A message displays when the App is created with a [Go to Resource] button to quickly open your Web App. (Note: You can also find your Web App by selecting "All Resources" in the left sidebar.)

The Web App Management blade displays, as shown in Fig. 4.

VSTSp3-04-WebAppManagment
Fig. 4

Select "Deployment Option" on the left menu of this blade to display the Deployment Option blade, as shown in Fig. 5.

VSTSp3-05-DeploymentOption
Fig. 5

Click "Choose Source" to display a list of Source repository types, as shown in Fig. 6.

VSTSp3-06-ChooseSource
Fig. 6

Select "Visual Studio Team Services".

You will return to the "Deployment Option" blade, but options specific to VSTS will now display, as shown in Fig. 7.

VSTSp3-07-DeploymentOptionVSTS
Fig. 7

Select your VSTS Account and Project from the dropdown. (Note: Your account and project will only appear if you have linked your VSTS project to Azure, as described here.)

Click the [OK] button to configure this automation.

It should take less than a minute to complete.

Any code currently in the project's repository will be deployed to Azure. You can see this by once again navigating to the Web App's URL (http://xxxx.azurewebsites.net).

Future code code pushed to the Team repository will also be deployed automatically to Azure.

In this article, you learned how to set up automatic deployment to an Azure Web App each time code is pushed to a VSTS project code repository.


This is Part 2 in a series of articles about integrating VSTS, Azure Web Apps, ASP.NET applications, and Visual Studio.

In my last post, I showed you how to create a new Team Account and Team project linked to Azure.

In this article, I will show how to open this new project in Visual Studio, start working with it, and check your code into VSTS Git repository.

To view your account and project in VSTS, open a new browser tab and navigate to https://xxxx.visualstudio.com/_admin

where xxxx is the name of the account you just created. You can see my account displayed in Fig. 1.

VSTSp2-01VisualStudioDotCom
Fig. 1

Click on the name of your project to display details about it, as shown in Fig. 2.

VSTSp2-02VstsProject
Fig. 2

Click the Code link at the top menu. If you have already checked in code, you will see that code in your Version Control Repository. New projects will look like my project, shown in Fig. 3.

VSTSp2-03VstsCode
Fig. 3

Click the [Clone in Visual Studio button]. This launch Visual Studio (You will probably be prompted to switch apps)

In Visual Studio, you should see the Team Explorer, as shown in Fig. 4. If you don't see it, you can find it by selecting View | Team Explorer from the menu.

VSTSp2-04VisualStudioTeamExplorer
Fig. 4

Click "Clone this repository" to display the Clone Repository dialog, as shown in Fig. 5.

VSTSp2-05VisualStudioTeamExplorerClone
Fig. 5

You have the opportunity to change where this new local repository will be saved on your hard drive. Whether you change it or not, you should note the location.

Click the [Clone] button. This will initialize a local GIT repository that points to your VSTS Team project.

You can now create a new Web App project in Visual Studio.

Select File | New | Project from the menu.     The "New Project" dialog displays, as shown in Fig. 6.

VSTSp2-06VisualStudioNewProject
Fig. 6

Under the "Templates" tree on the left, expand Visual C#; then select "Web". Select "ASP.NET Web Application" or "ASP.NET Core Web Application" as your template.

The location of your project is determined by the combination of the "Location" textbox and the "Solution name" textbox (assuming you have not unchecked "Create new directory for solution"). Verify that this points to the location of the local Git repository that was created above.

Uncheck the "Create new Git repository" checkbox.

Make any other desired changes and click the [OK] button to create a new button.

At the New ASP.NET Application dialog (Fig. 7), click [OK] to create the project. 

VSTSp2-07VisualStudioNewASPNetProject
Fig. 7

A new project will be created in the repository directory similar to the one shown in the Solution Explorer (View | Solution Explorer) in Fig. 8.

VSTSp2-08VisualStudioSolutionExplorer
Fig. 8

You can check this initial code into your version control repository from the Visual Studio Team Explorer (View | Team Explorer). Click the [Changes] button in the Team Explorer to display the Changes panel, as shown in Fig. 9.

VSTSp2-09Changes
Fig. 9

Enter a comment, such as “Initial commit” and click the [Commit All] button. This will commit your changes to the local Git Repository.

To push your changes up to the VSTS repository, you will need to access the Team Explorer Sync panel. You can navigate to this panel by clicking to dropdown near the top of the Changes panel and selecting “Sync” from the menu displayed, as shown in Fig. 10.

VSTSp2-10TeamExplorerDropdown
Fig. 10

The Sync panel displays, as shown in Fig. 11.

VSTSp2-11SyncPanel
Fig. 11

Click the “Sync” link. You should see a message indicating that the local and remote repositories are syncing, meaning that the local repository is merging any changes from the remote repository and your local commits are being pushed up to the remote repository in VSTS. The following message displays when this sync is complete:

Successfully synchronized incoming and outgoing commits.

If you return to the project code page in VSTS and refresh the web page, you should see all your code checked in. Fig. 12 shows my project after I checked in my initial commit.

VSTSp2-12VSTSCode
Fig. 12

In this article, I showed you how to create a new ASP.NET project in Visual Studio and store the code in an existing Visual Studio Team Systems Git repository.


This is Part 1 in a series of articles about integrating VSTS, Azure Web Apps, ASP.NET applications, and Visual Studio.

If you want to publish code from your repository to Azure, the easiest way to do this is to create the account from within the Azure portal.

Log into your Azure account and navigate to the portal by clicking the PORTAL link at the top right, as shown in Fig. 1.

VSTSp1-01-AzurePortalLink
Fig. 1

From the Azure portal, select

New | Developer Tools | Team project

as shown in Fig. 2.

VSTSp1-02AzureNewTeamProject-01
Fig. 2

The "New Team Project" blade displays, as shown in Fig. 3

VSTSp1-03NewTeamProject-1
Fig. 3

Enter a Name to identify this team.

Click "Configure required settings" under "Account"; then, click "Create a new account" and enter a name for your VSTS Account (Fig. 4). This name must be unique among all VSTS account, because it will be used in a URL to connect to the account.

VSTSp1-04NewTeamProject-2
Fig. 4

Click [OK] to close the "New Account" blade.

Review all the settings in the New Project dialog. You may wish to change the location, so that it is closer to your team members. (For me, this defaulted to Brazil, so I changed it to Central US). My completed blade is shown in Fig. 5.

VSTSp1-05NewTeamProject-3
Fig. 5

Click [Create] to begin creating the Team Project.

It may take a minute or two to create the VSTS Account and a project within that account.

To view the account and project in VSTS, open a new browser tab and navigate to https://xxxx.visualstudio.com/_admin

where xxxx is the name of the account you just created. You can see my account displayed in Fig. 6.

VSTSp1-06VSTSAccountAndProject
Fig. 6

In this article, I showed how to create a team project in VSTS and link it to Azure. In the next article, I will show how to create an ASP.NET application in Visual Studio and push that application’s code into this team project’s code repository.



<< Older Posts | Newer Posts >>