NASA’s Alien Planet Archive using PowerShell

Nasa has just opened up their Exoplanet Archive for the world. The archive contains exoplanet sightings by the Kepler observatory.

Click here for more information

The Exoplanet Archive data are accessed through the Exoplanet Archive’s application programming interface (API).

Click here for more information

Now for the fun stuff! Windows PowerShell Version 3.0 includes a CmdLet called Invoke-RestMethod. We can use the CmdLet to get data from Nasa’s API.

Before we download the data we need a query. All queries against the API must begin with the following base URL.


PS > $url = "http://exoplanetarchive.ipac.caltech.edu/cgi-bin/nstedAPI/nph-nstedAPI?"

Next we specify which data table to query. In the example below query the exoplanets table.


PS > $url = $url + "table=exoplanets"

We also add the names of the columns we want to be returned. In the example below we select the pl_hostname, and ra columns.


PS > $url = $url + "&select=pl_hostname,ra"

Here’s what the complete URL looks like.


PS > $url


http://exoplanetarchive.ipac.caltech.edu/cgi-bin/nstedAPI/nph-nstedAPI?table=exoplanets&select=pl_hostname,ra

Now we can use Invoke-Restmethod to download the data from Nasa.


PS > Invoke-RestMethod -Uri $url

pl_hostname,ra
HD 173416,280.900452
HD 175167,285.003479
HD 175541,283.920349
HD 176051,284.256714
HD 177830,286.336548
HD 177830,286.336548

The example above displays the csv data as lines of text. Converting the text to objects is a simple task in PowerShell v 3.0 thanks to the ConvertFrom-Csv CmdLet.


PS > Invoke-RestMethod -Uri $url | ConvertFrom-Csv

pl_hostname       ra
-----------       --
HD 173416         280.900452
HD 175167         285.003479
HD 175541         283.920349
HD 176051         284.256714
HD 177830         286.336548
HD 177830         286.336548

Let’s wrap up the code in a reusable function instead.

Click here to download the Get-ExoPlanet function.


function Get-ExoPlanet {
  <#
    .SYNOPSIS
    Gets data from the Exoplanet Archive.
  
    .DESCRIPITON
    Uses the Exoplanet Archive Application Programming Interface (API) to retrieve information regarding Exoplanets.
  
    .EXAMPLE
    Get-ExoPlanet
  #>
  [CmdletBinding(HelpUri = 'http://exoplanetarchive.ipac.caltech.edu/docs/program_interfaces.html')]
  param()
  process {
    # Check PowerShell Version.
    if($Host.Version.Major -ne 3) {
      Write-Warning -Message "This function requires PowerShell Version 3.0"
      break
    }
    # Data table to access (exoplanets or koi or tce)
    $table = "Exoplanets"

    # Only retrieve Common Columns
    [string[]]$Column = @("pl_hostname", "pl_letter", "pl_discmethod", "pl_orbper", "pl_orbsmax", "pl_orbeccen", "pl_massj", "pl_msinij", "pl_radj", "pl_dens", "pl_orbincl", "pl_ttvflag", "ra", "dec", "st_dist", "st_vj", "st_teff", "st_mass", "st_rad", "hd_name", "hip_name")

    # Uri.
    $uri = "http://exoplanetarchive.ipac.caltech.edu/cgi-bin/nstedAPI/nph-nstedAPI?table=" + $table + "&select=" + [string]::Join(",",$Column)

    # Get Data
    $result = Invoke-RestMethod -Uri $uri
    
    # Convert from Csv to PowerShell Object.
    $result | ConvertFrom-Csv | ForEach-Object {
      # Return as a Custom PowerShell Object
      New-Object PSObject -Property @{
        PlanetHostStarName = [string]$($_.pl_hostname);
        PlanetLetter = [string]$($_.pl_letter);
        DiscoveryMethod = [string]$($_.pl_discmethod);
        OrbitalPeriod = [double]$($_.pl_orbper);
        SemiMajorAxis = [double]$($_.pl_orbsmax);
        Eccentricity = [double]$($_.pl_orbeccen);
        PlanetMass = [double]$($_.pl_massj);
        PlanetMsin = [double]$($_.pl_msinij);
        PlanetRadius = [double]$($_.pl_radj);
        PlanetDensity = [double]$($_.pl_dens);
        Inclination = [double]$($_.pl_orbincl);
        TTVFlag = [double]$($_.pl_ttvflag);
        RightAscension = [double]$($_.ra);
        Declination = [double]$($_.dec);
        Distance = [double]$($_.st_dist);
        VJohnsonSystemMagnitude = [double]$($_.st_vj);
        EffectiveStellarTemperature = [double]$($_.st_teff);
        StellarMass = [double]$($_.st_mass);
        StellarRadius = [double]$($_.st_rad);
        HDName = [string]$($_.hd_name);
        HIPName = [string]$($_.hip_name)
      }
    }
  }
}

Now we can simply type Get-ExoPlanet to display the data from NASA’s Alien Planet Archive.


PS > $exoPlanets = Get-ExoPlanet
PS > $exoPlanets

PlanetLetter                : b
PlanetDensity               : 0
StellarMass                 : 0
VJohnsonSystemMagnitude     : 6.037
HDName                      : HD 173416
OrbitalPeriod               : 323.6
PlanetRadius                : 0
Declination                 : 36.556606
SemiMajorAxis               : 1.16
StellarRadius               : 0
Inclination                 : 0
Eccentricity                : 0.21
RightAscension              : 280.900452
Distance                    : 134.95
TTVFlag                     : 0
PlanetMsin                  : 2.7
DiscoveryMethod             : Radial Velocity
PlanetMass                  : 0
EffectiveStellarTemperature : 0
HIPName                     : HIP 91852
PlanetHostStarName          : HD 173416

The function displays the “default” columns from the Exoplanet Archive.

Working with the data as powershell objects allows us to combine the objects with other PowerShell CmdLets.

If we want to group the Exoplanets by Planet Letter we simply type:


PS > $exoPlanets | Group-Object PlanetLetter

Count Name                      Group
----- ----                      -----
  638 b                         {@{PlanetLetter=b;
  124 c                         {@{PlanetLetter=c;
   33 d                         {@{PlanetLetter=d;
   12 e                         {@{PlanetLetter=e;
    6 f                         {@{PlanetLetter=f;
    3 g                         {@{PlanetLetter=g;
    1 h                         {@{PlanetLetter=h;

Sorting the objects is also a simple task. Let’s say we want to display the top 10 planets with the largest Planet Mass (Jupiter).


PS > $exoPlanets | Sort-Object PlanetMass -Descending | 
Select-Object PlanetHostStarName , PlanetMass -First 10

PlanetHostStarName       PlanetMass
------------------       ----------
2MASS J22062280-2047058A      31.42
2MASS J07464256+2000321A      31.42
Kepler-47                        28
KELT-1                        27.23
nu Oph                           27
nu Oph                           24
HIP 78530                     23.04
HD 180314                        22
HN Peg                      21.9987
CoRoT-3                       21.66

If we want to display the Data in a Gridview we can pipe the objects to the Out-GridView CmdLet.


PS > $exoPlanets | Out-GridView

And if we want to Export the data to a Csv file we type:


PS > $exoPlanets | Export-Csv C:\ExoPlanets.csv

Click here to download the Get-ExoPlanet function.

Rating 4.50 out of 5
[?]

Checking Battery Status using PowerShell and PInvoke

You can use PowerShell when checking the battery status on your laptop.

One way of doing this is by using wmi as Scripting Guy demonstrates here.

Another way is by using P/Invoke to call unmanaged Win32 APIs from managed code.
In this example we will use GetSystemPowerStatus.

First we store the C# signature in a here-string, The signature is described here. Note the we add the public declaration.
We also add the SYSTEM_POWER_STATUS struct. The structure is described here.


$signature = @"
 [DllImport("kernel32.dll", SetLastError = true)]
 public static extern Boolean GetSystemPowerStatus(out SystemPowerStatus sps);

 public struct SystemPowerStatus
 {
  public Byte ACLineStatus;
  public Byte BatteryFlag;
  public Byte BatteryLifePercent;
  public Byte Reserved1;
  public Int32 BatteryLifeTime;
  public Int32 BatteryFullLifeTime;
 }
"@

Next, we add the call to Add-Type and place it in a custom namespace (to prevent it from colliding with other classes).


Add-Type -MemberDefinition $signature -Name PowerStatus -Namespace PowerStatus

Now, we use New-Object to create an instance of PowerStatus.PowerStatus+SystemPowerStatus.


$systemPowerStatus = New-Object PowerStatus.PowerStatus+SystemPowerStatus

Next we call the static method GetSystemPowerStatus() and reference $systemPowerStatus.


[void][PowerStatus.PowerStatus]::GetSystemPowerStatus([ref]$systemPowerStatus)

Now we can call the variable to display the current Power Status.


$systemPowerStatus

ACLineStatus        : 1
BatteryFlag         : 1
BatteryLifePercent  : 99
Reserved1           : 0
BatteryLifeTime     : -1
BatteryFullLifeTime : -1

Next step is to convert the numeric values to values we understand. Each memeber is described in the following MSDN Article.

The ACLineStatus can be one of the following values:

  • 0 = Offline
  • 1 = Online
  • 255 = Unknown status

Let’s change the numeric value using a switch.


$acLineStatus = 
 switch( [byte]$systemPowerStatus.ACLineStatus) {
  0 { "Offline" }
  1 { "Online" }
  255 { "Unknown status" }
  default { "Unknown status" }
}

The BatteryFlag can be one of the following values:

  • 0 = Not Charging, between 66% and 33%
  • 1 = High. The battery capacity is at more than 66 percent
  • 2 = Low. The battery capacity is at less than 33 percent
  • 4 = Critical. The battery capacity is at less than five percent
  • 8 = Charging
  • 128 = No system battery
  • 255 = Unknown status—unable to read the battery flag information

We’ll use a switch again to determine the BatteryFlag.


$batteryStatus =
switch( [byte]$systemPowerStatus.BatteryFlag) {
 0 { "Not Charging, between 66% and 33%" }
 1 { "High. The battery capacity is at more than 66 percent" }
 2 { "Low. The battery capacity is at less than 33 percent" }
 4 { "Critical. The battery capacity is at less than five percent" }
 8 { "Charging" }
 128 { "No system battery" }
 255 { "Unknown status—unable to read the battery flag information" }
 default { "Unknown"}
}

The BatteryLifePercent displays the percentage of full battery charge remaining. This can be a value in the range 0 to 100, or 255 if status is unknown. Here we use an if/else statement.


# Check Battery Life Percent
if( [byte]$systemPowerStatus.BatteryLifePercent -eq [byte]255 ) {
 $batteryLifePercent = "Unknown"
} else {
 $batteryLifePercent = [byte]$systemPowerStatus.BatteryLifePercent
}

The BatteryLifeTime displays the number of seconds of battery life remaining, or –1 if remaining seconds are unknown. Again we’ll use an if/else statement to determine the batteries lifetime.


# Check Battery Lifetime
if( $systemPowerStatus.BatteryLifeTime -eq -1 ) {
 $batteryLifeTime = "Unknown"
} else {
 $batteryLifeTime = (Get-Date).AddSeconds($systemPowerStatus.BatteryLifeTime)
}

Now we can simply use New-Object and create a custom object containing the information gathered.


New-Object PSObject -Property @{
 ACPowerStatus = $acLineStatus;
 BatteryStatus = $batteryStatus;
 BatteryLifePercent = $batteryLifePercent
 BatteryLifeTime = $batteryLifeTime
 ComputerName = $env:COMPUTERNAME
} | Select-Object ACPowerStatus, BatteryStatus, BatteryLifePercent, BatteryLifeTime, ComputerName

And finally, here’s a reusable function that simplifies the steps

Rating 4.00 out of 5
[?]

Block and Unblock Keyboard & Mouse input using PowerShell

You can use PowerShell to either block or unblock Keyboard & Mouse input. This is useful if you temporary need to block user input.

In this example we are going to use PInvoke to perform a keyboard & mouse lock.

The technique is described here: http://www.pinvoke.net/default.aspx/user32/BlockInput.html

If you want to learn how to call the Native Windows APIs, check out PInvoke.net.
Pinvok.net is a wiki that allows developers to share PInvoke signatures,
user-defined types, and any other info related to calling Win32 and other unmanaged APIs from managed code (C# VB.NET and PowerShell).

First we use the sample code from P/Invoke in PowerShell.
Thanks to the Add-Type CmdLet, we can simply place the C# sample code in a variable and pass it to the CmdLet using the MemberDefinition parameter.

$signature = @"
  [DllImport("user32.dll")]
  public static extern bool BlockInput(bool fBlockIt);
"@

Next, we use the Add-Type CmdLet.

$block = Add-Type -MemberDefinition $signature -Name DisableInput -Namespace DisableInput -PassThru

Finally, we call the static method BlockInput and input boolean $true.

$block::BlockInput($true)

At this point your keyboard and mouse should be blocked. (You can always press ctrl+alt+delete to override the lock).

Unblocking the keyboard and mouse is just as simple. You just need to input boolean $false to the method as shown below.

$block::BlockInput($false)

A simple way of using these techniques in a script is by placing the code in functions.

Here’s the Block function.

function Block-TSKeyboardInput {
$signature = @"
  [DllImport("user32.dll")]
  public static extern bool BlockInput(bool fBlockIt);
"@

$block = Add-Type -MemberDefinition $signature -Name DisableInput -Namespace DisableInput -PassThru
$block::BlockInput($true)
}

And here’s the Unblock function.

function Unblock-TSKeyboardInput {
$signature = @"
  [DllImport("user32.dll")]
  public static extern bool BlockInput(bool fBlockIt);
"@

$unBlock = Add-Type -MemberDefinition $signature -Name EnableInput -Namespace EnableInput -PassThru
$unBlock::BlockInput($false)
}

The Example below demonstrates how to lock the Keyboard & Mouse for 10 seconds.

Block-TSKeyboardInput
Start-Sleep -Seconds 10
Unblock-TSKeyboardInput

Rating 4.00 out of 5
[?]

For relaxing times, make it Umeå times.

Here’s a function dedicated to my friends in Umeå who attended my 8-day PowerShell Course,
special thanks to Roger!

 

You can display the types available by writing:

 

 

The example above displays the different types available.

 

If you want to search for a specific type you can simply write:

 

 

You can also search by name as shown below.

 

 

And here’s an example of pipe:ing the objects to Out-GridView.

 

 

Click here to download the function.

 

Rating 4.67 out of 5
[?]