Category Archives: Code Tips

CleanWork for Windows

Recently, we decided to go back through some of our older programs and take a look at them and see if they could be updated and/or made open source. We wrote Cleanwork years ago and we often provided it to organizations that used our consulting services as a freebie and a way to say “Thank You.”

CleanWork does pretty much what the name says. It is a WPS program that when run, will clean out the work folders of old and orphaned directories that are no longer used. WPS comes with a cleanwork program for Linux and Mac but not for Windows. The version written by MineQuest will run on Windows Workstations running Vista, 7, 8, 8.1 and 10. It will also run on Windows Servers such as Windows Server 2008, 2008 R2, 2012 and 2012 R2. Basically, it will run on all Windows Servers except 2003 and before. It also runs on all Windows Workstations except XP and before.

Cleanwork is packaged in a zip file that contains the source code, the Usage Document, License and a sample program. Cleanwork has been tested to execute only on the WPS platform.

If you are running WPS on a Windows Server you may want to set cleanwork to run on a schedule. This is a perfect utility to automate and run on a regular schedule. For busy server installations, I could see setting a scheduler to run cleanwork every few hours.

The zip file contains five files. These are:

clean.sas – a sample program for running the cleanwork utility.

cleanwork_source.sas – the actual source code that implements the utility.

CleanWorkUsage.docx – a Microsoft Word document that explain how to use cleanwork.

SASMACR.wpccat – a compiled version of the macro that  is ready to run.

license.txt – The license agreement for use of the source code and user document.

You can find the download by going to the bottom of the page here.

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

 

 

 

Plotting Points on a Street Level Map using the Bridge to R and WPS

In the last few installments of this blog, I have shown how you can use WPS and the Bridge to R to calculate drive distances, geocode records and pull down a map from Google maps. I want to use this post to pull all this together and show how you can geocode your addresses and plot them on a street level map.

First some background you need to know about using Google for geocoding and mapping. There are limits to what Google will allow you to do with their services before they want you to start paying. You can geocode 2,500 records a day for free. You can pull down 25,000 maps a day for free. Once you start moving past these limits, there are fees involved.

One thing that you should probably start to consider is caching records locally that have been geocoded so that you don’t have to go back to the Google geocoder every time you want to plot some points on a map. I could easily run through 2,500 addresses in a day. The limitations on the number of maps is just not an issue for me. I think 25,000 maps a day is a very liberal offering for the kind of work that I would want to use the service for.

In the sample code below, I split the mapping process into two components for ease in understanding the entire process. I first geocode the file to get the latitude and longitude for each record. The second part of the process is creating a map and using the lat’s and long’s to plot points on the map. We could have put this into a single step but it wouldn’t be as clear or as flexible.

Without further ado, here’s the code using the Bridge to R and WPS.

data gasstations;
input company $1-29 address $30-52 city $53-64 state $66-67;
addr2geocode=trim(address)||', '||trim(city)||', '||trim(state);
cards;
Citgo Gas Station            5189 28th St Se        Grand Rapids MI
28th Street BP               5155 28th St Se        Grand Rapids MI
Twenty-Eighth Street C Store 5556 28th St Se        Grand Rapids MI
Speedway                     4045 28th St Se        Grand Rapids MI
Speedway                     2305 E Paris Ave Se    Grand Rapids MI
Superamerica                 2305 E Paris Ave Se    Grand Rapids MI
Shell Food Mart              3960 28th St Se        Grand Rapids MI
Admiral Petroleum            3927 28th St Se        Grand Rapids MI
Cascade C Store              4591 Cascade Rd Se     Grand Rapids MI
Friendly Food Shops          6799 Cascade Rd Se     Grand Rapids MI
Family Fare Quick Stop       6799 Cascade Rd Se     Grand Rapids MI
Cascade Citgo                6820 Cascade Rd Se     Grand Rapids MI
Dutton Fuel Mart LLC         2560 E Beltline Ave Se Grand Rapids MI
Centerpointe Marathon        2560 E Beltline Ave Se Grand Rapids MI
Shell Food Mart              2600 E Beltline Ave Se Grand Rapids MI
Speedway                     4018 Cascade Rd Se     Grand Rapids MI
Grand Rapids Gas Incorporated3214 28th St Se        Grand Rapids MI
Cascade Shell                4033 Cascade Rd Se     Grand Rapids MI
Speedway                     4665 44th St Se        Kentwood     MI
Super Petroleum Incorporated 2411 28th St Se        Grand Rapids MI
;;;;
run;


*--> Geocode the addresses using the Google Geocoder. Keep the geocoded records
     in the output dataset names locs for further processing.;

%rstart(dataformat=csv,data=gasstations,rGraphicsFile=);
datalines4;

## options(repos=structure(c(CRAN="http://cran.case.edu/")))
## install.packages("ggmap", dependencies = FALSE)

   attach(gasstations)

   library(ggmap)

   gaddress <- as.character(gasstations$addr2geocode)
   locs <- geocode(gaddress,output="more")

;;;;
%rstop(import=locs);


*--> Pull a Google map that is centered on a particular address and plot the locations
     on the map. Use the data set that was created (locs) above that contains the 
     lat and longs to plot the points.;
     
Title 'Gas Stations on or Near 28th Street';
Title2 'Grand Rapids, Michigan';     
     
%rstart(dataformat=csv,data=locs,rGraphicsFile=);
datalines4;

attach(locs)
addr <- locs;

library(ggmap)

map.center <- geocode('3960 28th St Se, Grand Rapids, MI');

 grmap <- qmap(c(lon=map.center$lon, lat=map.center$lat), zoom = 13,color = 'color', legend = 'topleft')
          grmap +geom_point(aes(x = lon, y = lat, size=3.0), data = addr)

;;;;
%rstop(import=);

The map that is created looks like this:

GR_Stations

I cropped this down a bit and got rid of the borders so that it would be easier to view on this blog. Note the black points on the map that indicate the locations of the gas stations. We could continue this exercise by plotting a label to the points with the names of the service stations but that would be a good exercise for the reader who wants to learn more about using ggmap and street level mapping.

If you want to learn more about ggmap and street level mapping, I encourage you to take a look at the following document, “ggmap: Spatial Visualization with ggplot2 – the R Journal” and can be viewed in PDF format here. What I have presented is really a quick and dirty set of examples that just begin to scratch the surface of what ggmap can do for you.

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

Creating a Street Level Map with WPS and the Bridge to R

Creating a street level map using the Bridge to R and WPS is actually pretty easy. As in our other examples (see the two previous blogs) we again use ggmap to pull down a map from Google Maps and display it using HTML. Amazingly, this only takes four lines of R code. Here’s an example:

 

%rstart(dataformat=man,data=,rGraphicsFile=);
datalines4;

   library(ggmap)

   bp <- "4045 28th St Se, Grand Rapids, MI, USA"
   qmap(bp, zoom=12)
   print(bp)

;;;;
%rstop(import=);

The code is fairly easy to follow. We load the ggmap library that will do most of the work for us. We center the map using the address “4045 28th St Se, Grand Rapids, MI, USA”. The next line queries the map with a specified zoom level (we are using zoom level 12). Finally, we print the map using the print function.

This is what the map looks like.

b2rplt_1700486050_2_1

 

We can actually take this a bit further. Instead of using a known address, we can us a place of interest for querying and creating the map. If we replace the address in the code above with “White House, Washington DC, USA” we get a map like below.

b2rplt_1700487946_3_1

So know we have seen how easy it is to pull down a map from Google using ggmap and the Bridge to R for WPS. If you have a copy of the Bridge to R, I recommend you play with the demonstration programs to get an idea of what you can do with the software and the mapping service. It’s always fun to see what gets rendered using ggmap, R and the Bridge to R.

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

Geocoding with WPS and the Bridge to R

 

One of the things that I truly enjoy is the flexibility of the language of SAS and how well WPS allows you to integrate the product with other services. One aspect of research, whether you are in the social sciences, marketing or some other area of study is the use and application of location data. 

I’m not talking necessarily about getting the data from your cell phone on where you are or have been, but in taking address data and using it to create a business advantage. Visualizing data on a map is important for many people but it’s often a laborious task to get all the data enhanced so that it can be mapped or plotted. Specifically, I’m talking about taking an address and finding additional information such as political districts and latitude and longitude for each address.

Using the Bridge to R and WPS, we can use R to geocode our data. In our example, we will use ggmap which was developed and written by Hadley Wickham and David Kahle. It is a truly amazing application and every time I use it, I learn something new.

In this example, I have 20 records that have the name and address of gas stations in Cascade Township which is a part of Grand Rapids, Michigan. What we want to do is geocode these 20 records to find their latitude and longitude. Below is the entire code snippet to do just that.

data gasstations;
input company $1-29 address $30-52 city $53-64 state $66-67;
addr2geocode=trim(address)||', '||trim(city)||', '||trim(state);
cards;
Citgo Gas Station            5189 28th St Se        Grand Rapids MI
28th Street BP               5155 28th St Se        Grand Rapids MI
Twenty-Eighth Street C Store 5556 28th St Se        Grand Rapids MI
Speedway                     4045 28th St Se        Grand Rapids MI
Speedway                     2305 E Paris Ave Se    Grand Rapids MI
Superamerica                 2305 E Paris Ave Se    Grand Rapids MI
Shell Food Mart              3960 28th St Se        Grand Rapids MI
Admiral Petroleum            3927 28th St Se        Grand Rapids MI
Cascade C Store              4591 Cascade Rd Se     Grand Rapids MI
Friendly Food Shops          6799 Cascade Rd Se     Grand Rapids MI
Family Fare Quick Stop       6799 Cascade Rd Se     Grand Rapids MI
Cascade Citgo                6820 Cascade Rd Se     Grand Rapids MI
Dutton Fuel Mart LLC         2560 E Beltline Ave Se Grand Rapids MI
Centerpointe Marathon        2560 E Beltline Ave Se Grand Rapids MI
Shell Food Mart              2600 E Beltline Ave Se Grand Rapids MI
Speedway                     4018 Cascade Rd Se     Grand Rapids MI
Grand Rapids Gas Incorporated3214 28th St Se        Grand Rapids MI
Cascade Shell                4033 Cascade Rd Se     Grand Rapids MI
Speedway                     4665 44th St Se        Kentwood     MI
Super Petroleum Incorporated 2411 28th St Se        Grand Rapids MI
;;;;
run;

proc print data=gasstations;
var addr2geocode;
run;


%rstart(dataformat=csv,data=gasstations,rGraphicsFile=);
datalines4;

   attach(gasstations)

   library(ggmap)

   gaddress <- as.character(gasstations$addr2geocode)
   locs <- geocode(gaddress,output="more")

;;;;
%rstop(import=locs);

proc print data=locs(drop=var2);
run;

The output that is returned from the PROC Print looks like:

                                                 The WPS System                     19:07 Thursday, November 14, 2013    1
                                                                                                                                    
 Obs          lon          lat type             loctype                                                                             
                                                                                                                                    
   1  -85.5396645   42.9127946 street_address   rooftop                                                                             
   2   -85.540616    42.913151 street_address   rooftop                                                                             
   3  -85.5308863   42.9129211 street_address   range_interpolated                                                                  
   4  -85.5678243   42.9128289 street_address   rooftop                                                                             
   5  -85.5692342    42.921498 street_address   range_interpolated                                                                  
   6  -85.5692342    42.921498 street_address   range_interpolated                                                                  
   7  -85.5685794   42.9125298 street_address   range_interpolated                                                                  
   8  -85.5700129   42.9125533 street_address   range_interpolated                                                                  
                                                                                                                                    
 Obs address                                                                                               north        south       
                                                                                                                                    
   1 5189 28th street southeast, grand rapids, mi 49508, usa                                         42.91414358  42.91144562       
   2 5155 28th street southeast, grand rapids, mi 49512, usa                                         42.91449998  42.91180202       
   3 5556 28th street southeast, grand rapids, mi 49512, usa                                         42.91427683  42.91157887       
   4 4045 28th street southeast, grand rapids, mi 49512, usa                                         42.91417788  42.91147992       
   5 2305 east paris avenue southeast, grand rapids, mi 49546, usa                                   42.92284723  42.92014927       
   6 2305 east paris avenue southeast, grand rapids, mi 49546, usa                                   42.92284723  42.92014927       
   7 3960 28th street southeast, grand rapids, mi 49512, usa                                         42.91388553  42.91118757       
   8 3927 28th street southeast, grand rapids, mi 49512, usa                                         42.91389553  42.91119757       
                                                                                                                                    
 Obs         east         west  postal_code country         administrative_area_level_2 administrative_area_level_1 locality        
                                                                                                                                    
   1 -85.53831552 -85.54101348        49508 united states             kent                      michigan            grand rapids    
   2 -85.53926702 -85.54196498        49512 united states             kent                      michigan            grand rapids    
   3 -85.52953782 -85.53223578        49512 united states             kent                      michigan            grand rapids    
   4 -85.56647532 -85.56917328        49512 united states             kent                      michigan            grand rapids    
   5 -85.56787602 -85.57057398        49546 united states             kent                      michigan            grand rapids    
   6 -85.56787602 -85.57057398        49546 united states             kent                      michigan            grand rapids    
   7 -85.56723042 -85.56992838        49512 united states             kent                      michigan            grand rapids    
   8 -85.56866387 -85.57136183        49512 united states             kent                      michigan            grand rapids    
                                                                                                                                    
 Obs street                                  streetNo point_of_interest query                                                       
                                                                                                                                    
   1 28th street southeast                       5189        NA         5189 28th St Se, Grand Rapids, MI                           
   2 28th street southeast                       5155        NA         5155 28th St Se, Grand Rapids, MI                           
   3 28th street southeast                       5556        NA         5556 28th St Se, Grand Rapids, MI                           
   4 28th street southeast                       4045        NA         4045 28th St Se, Grand Rapids, MI                           
   5 east paris avenue southeast                 2305        NA         2305 E Paris Ave Se, Grand Rapids, MI                       
   6 east paris avenue southeast                 2305        NA         2305 E Paris Ave Se, Grand Rapids, MI                       
   7 28th street southeast                       3960        NA         3960 28th St Se, Grand Rapids, MI                           
   8 28th street southeast                       3927        NA         3927 28th St Se, Grand Rapids, MI                                                                                      The WPS System                     19:07 Thursday, November 14, 2013    2
                                                                                                                                    
 Obs          lon          lat type             loctype                                                                             
                                                                                                                                    
   9   -85.556224    42.946438 street_address   rooftop                                                                             
  10    -85.50019    42.915388 street_address   rooftop                                                                             
  11    -85.50019    42.915388 street_address   rooftop                                                                             
  12   -85.499809    42.913584 street_address   rooftop                                                                             
  13   -85.583252    42.916731 street_address   rooftop                                                                             
  14   -85.583252    42.916731 street_address   rooftop                                                                             
  15   -85.583243    42.916087 street_address   rooftop                                                                             
  16   -85.570236    42.947743 street_address   rooftop                                                                             
                                                                                                                                    
 Obs address                                                                                               north        south       
                                                                                                                                    
   9 4591 cascade road southeast, grand rapids, mi 49546, usa                                        42.94778698  42.94508902       
  10 6799 cascade road southeast, grand rapids, mi 49546, usa                                        42.91673698  42.91403902       
  11 6799 cascade road southeast, grand rapids, mi 49546, usa                                        42.91673698  42.91403902       
  12 6820 cascade road southeast, grand rapids, mi 49546, usa                                        42.91493298  42.91223502       
  13 2560 east beltline avenue southeast, centerpointe mall, grand rapids, mi 49546, usa             42.91807998  42.91538202       
  14 2560 east beltline avenue southeast, centerpointe mall, grand rapids, mi 49546, usa             42.91807998  42.91538202       
  15 2600 east beltline avenue southeast, centerpointe mall, grand rapids, mi 49546, usa             42.91743598  42.91473802       
  16 4018 cascade road southeast, grand rapids, mi 49546, usa                                        42.94909198  42.94639402       
                                                                                                                                    
 Obs         east         west  postal_code country         administrative_area_level_2 administrative_area_level_1 locality        
                                                                                                                                    
   9 -85.55487502 -85.55757298        49546 united states             kent                      michigan            grand rapids    
  10 -85.49884102 -85.50153898        49546 united states             kent                      michigan            grand rapids    
  11 -85.49884102 -85.50153898        49546 united states             kent                      michigan            grand rapids    
  12 -85.49846002 -85.50115798        49546 united states             kent                      michigan            grand rapids    
  13 -85.58190302 -85.58460098        49546 united states             kent                      michigan            grand rapids    
  14 -85.58190302 -85.58460098        49546 united states             kent                      michigan            grand rapids    
  15 -85.58189402 -85.58459198        49546 united states             kent                      michigan            grand rapids    
  16 -85.56888702 -85.57158498        49546 united states             kent                      michigan            grand rapids    
                                                                                                                                    
 Obs street                                  streetNo point_of_interest query                                                       
                                                                                                                                    
   9 cascade road southeast                      4591        NA         4591 Cascade Rd Se, Grand Rapids, MI                        
  10 cascade road southeast                      6799        NA         6799 Cascade Rd Se, Grand Rapids, MI                        
  11 cascade road southeast                      6799        NA         6799 Cascade Rd Se, Grand Rapids, MI                        
  12 cascade road southeast                      6820        NA         6820 Cascade Rd Se, Grand Rapids, MI                        
  13 east beltline avenue southeast              2560        NA         2560 E Beltline Ave Se, Grand Rapids, MI                    
  14 east beltline avenue southeast              2560        NA         2560 E Beltline Ave Se, Grand Rapids, MI                    
  15 east beltline avenue southeast              2600        NA         2600 E Beltline Ave Se, Grand Rapids, MI                    
  16 cascade road southeast                      4018        NA         4018 Cascade Rd Se, Grand Rapids, MI                                                                                   The WPS System                     19:07 Thursday, November 14, 2013    3
                                                                                                                                    
 Obs          lon          lat type             loctype                                                                             
                                                                                                                                    
  17  -85.5879549    42.912112 street_address   rooftop                                                                             
  18   -85.569238    42.948355 street_address   rooftop                                                                             
  19  -85.5499342   42.8836312 street_address   range_interpolated                                                                  
  20   -85.607639    42.912997 street_address   rooftop                                                                             
                                                                                                                                    
 Obs address                                                                                               north        south       
                                                                                                                                    
  17 3214 28th street southeast, grand rapids, mi 49512, usa                                         42.91346098  42.91076302       
  18 4033 cascade road southeast, grand rapids, mi 49546, usa                                        42.94970398  42.94700602       
  19 4665 44th street southeast, kentwood, mi 49512, usa                                             42.88497343  42.88227547       
  20 2411 28th street southeast, grand rapids, mi 49512, usa                                         42.91434598  42.91164802       
                                                                                                                                    
 Obs         east         west  postal_code country         administrative_area_level_2 administrative_area_level_1 locality        
                                                                                                                                    
  17 -85.58660592 -85.58930388        49512 united states             kent                      michigan            grand rapids    
  18 -85.56788902 -85.57058698        49546 united states             kent                      michigan            grand rapids    
  19 -85.54858527 -85.55128323        49512 united states             kent                      michigan            kentwood        
  20 -85.60629002 -85.60898798        49512 united states             kent                      michigan            grand rapids    
                                                                                                                                    
 Obs street                                  streetNo point_of_interest query                                                       
                                                                                                                                    
  17 28th street southeast                       3214        NA         3214 28th St Se, Grand Rapids, MI                           
  18 cascade road southeast                      4033        NA         4033 Cascade Rd Se, Grand Rapids, MI                        
  19 44th street southeast                       4665        NA         4665 44th St Se, Kentwood, MI                               
  20 28th street southeast                       2411        NA         2411 28th St Se, Grand Rapids, MI                           
                                                                                                                

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

On ErrorAbend

One issue I always had with the SAS system as a developer was when I had a job that ran in batch that had an error. The SAS System would set the number of observations to zero and go into syntax checking mode for the remainder of the program.

This had some virtues but more often than not, the error was thrown because I had misspelled a variable name in a MEANS statement or FREQ statement that was used for checking my output. This would cause SAS to go into the syntax checking mode and all the rest of my program would not execute even though it was proper.

WPS, when running in batch doesn’t do this but if you want the same effect for your batch jobs, it’s easy enough to implement. Consider the following macro – called %ErrorAbend. %ErrorAbend simply checks that the program is not running in the FOREground and checks the value of the &syserr variable after every PROC or data step and if it returns a value of 3, then issues a note and sets the number of observations to zero.

%macro onerrorabend;
  %if %eval(&syserr eq 3) and &sysenv NE FORE %then %do;
     options obs=0;
     %put NOTE: WPS has been set with OPTION OBS=0 and will continue to check statements.
  %end;
%mend;

Below is a sample program that when run in batch, puts the system into syntax checking mode and basically stops the execution of any downstream statements.

data a b;
do ii=1 to 2000;
  x=ranuni(0)* 10;
  y=Round(ranuni(0),.01)* 100;
  z=round(ranuni(0),.01)* 10000;
  

  a=ranuni(0)* 10;
  b=Round(ranuni(0),.01)* 100;
  c=round(ranuni(0),.01)* 10000;
  
  e=ranuni(0)* 10;
  f=Round(ranuni(0),.01)* 100;
  g=round(ranuni(0),.01)* 10000;
  
  i=ranuni(0)* 10;
  j=Round(ranuni(0),.01)* 100;
  k=round(ranuni(0),.01)* 10000;

  output;
end;
run;

proc freq data=a;
tables ik;
run;

%onerrorabend;


proc means data=b;
run;

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

Integrating WPS and Skype

One of the things I like to do in programming is integrating other tools with WPS. I don’t know why I find that so fun to do, but I just find it rewarding for some reason. Every once in a while, I stumble across a problem to be solved and it just seems like it should be something that is easy, simply because it’s so useful. That is rarely the case as we all know.

I always wanted to have some way for an interactive WPS job or a WPS batch job to notify me of an error when it reaches completion or to notify me that it has reached a certain point in the job process. One of the main requirements is that the notification be sent by text message so that I could be notified if I wasn’t sitting directly in front of the monitor of the machine that the code was submitted on.

We have been able to send text messages for years (see “Sending SMS Text via WPS”) but that was kind of clumsy because as far as I could tell, it would only send the message to my cell phone. I want more! Give me more!

Skype is the logical choice for me because I sit in front of a PC most of the day that has Skype running. I also have Skype installed on Skype is the logical choice for me because I sit in front of a PC most of the day that has Skype running. I also have Skype installed on mobile Apple and Android devices so I can receive messages through those devices pretty easily.

All I needed to do is install Skype on a Windows Server. The Server I installed it on is running Windows Essentials 2012 R2. Getting Skype on that platform can be a chore but it can be done. I ended up installing the Windows 8 version of Skype on the server and after getting it to run properly (i.e. sending and receiving messages) I installed the classic Skype for Desktop on the machine. If you are running a previous version of Windows Server… well good luck on getting it to install.

Usage

%WPS2Skype(SkypeID=minequest_llc,

                         category=-U,

                         SkypeMsgTxt = “Your job reached the halfway point you awesome guy!”);

 

Where

SkypeID is the ID of the recipient of the message

Category = -U or –CC

SkypeMsgTxt =”Your message text here.”

 

If you are a WPS programmer or are familiar with the macro language, then the above should be self-explanatory with the exception of Category. Category can take one of two options, either –U or –CC. If we want to send the message to an individual user than we use –U. If we want to send the message to a list of contacts then we use –CC. A contact list is somewhat similar to a group and you should read up on what a contact list is and how it can be created in the Skype documentation.

Running the following code:

%WPS2Skype(SkypeID=xxxxxxxxxx,

                         category=-U,

                         SkypeMsgTxt = “Your job reached the halfway point you awesome guy!”);

 

We see in the WPS log the output when the message was sent:

 

2         %WPS2Skype(SkypeID=xxxxxxxxxx,

3         category=-U,

4         SkypeMsgTxt=”Your job reached the halfway point you awesome guy!”);

 

NOTE: WPS2Skype returned execution to WPS.

 

And what I see in the Skype message window on my workstation is:

 

 

 

clip_image001

 

 

Of course, this will show up on all the devices that I have logged in to Skype using my Skype ID.

 

I also extended the Skype interface into the RunWPS.CMD file. The RunWPS.CMD is a Windows command file that allows you to run WPS as a batch job. With the integration of Skype with RunWPS.CMD, I catch all return codes from WPS and send out a Skype message if the return code is greater than zero. This is easily modified but I’m not personally interested in getting messages when jobs complete properly. I’m only interested when jobs terminate abnormally.

 

The WPS2SKYPE utility will be available in our next release. There are a few more utilities that I want to add to the package and I still have documentation that needs to either be written or cleaned up.

 

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

Sending SMS Text via WPS

As mobile has become ubiquitous in our culture, it’s become more of the norm to utilize cell phones and tablets in both our business and personal life. There’s a seismic shift in personal computing that has impacted us in both the work place as well as at home. Our phones and tablets are basically used as a consumer device. As a consumer device, I mean a gadget that we don’t program on to do various things, but a device to alert us and to keep us informed.

One of the interesting applications that can be done with WPS is the use of email from within your WPS application. For example, you can format a report and send it via email to those folks who need to see it as opposed to having to send emails manually. One cool thing is that you can also use WPS to send a text message via the WPS application.

There could be a use for sending a SMS message via your WPS program. For example, one use could be to notify you that a long running job has run to completion or has thrown an error code.

To send a text message, you need to find your cell phone’s gateway before you can send an SMS message. Below is a table with the four largest carriers in the United States with their respective gateways.

 

Table 1. Major Carriers SMS Gateway Addresses.

AT&T

number@txt.att.net

Sprint

number@messaging.sprintpcs.com

T-Mobile

number@tmomail.net

Verizon

number@vtext.com

Here is the basic code to send a text message via email using WPS. Of course, you could enhance the functionality of the code below and wrap it in a macro to make it even easier to use.

   1: FILENAME mail EMAIL "5555555555@vtext.com"

   2:          SUBJECT="Message from WPS: ";

   3:  

   4: data _null_;

   5:   file mail;

   6:   PUT "Program DAILY-BUILD has completed. Check log file for errors.";

   7:   PUT "!EM_SEND!";

   8: Run;

One issue that you are likely to encounter is that you will receive a message from Outlook or Windows Mail confirming that YOU are trying to send an email as opposed to a rogue program attempting doing it.

You can overcome this validation by using Context Magic’s ClickYes application or alternatively MapiLabs Outlook Security application.

image

You can overcome this validation check by using Context Magic’s ClickYes application or alternatively MapiLabs Outlook Security application.

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

Analytic Workstations – Conclusions

Continued from: Analytic Workstations – Part III

After going through a few days of tests and tuning on the new workstation, I can say I’m satisfied with the results. I’m sure I could squeak out a few more seconds here and there as it pertains to reductions in run times but I don’t think it is worth the additional effort.

Going forward, I think it would be an interesting exercise to examine the effect of swapping out the Intel I5 processor for an Intel I7. That would take the workstation from a four core to an eight core (i.e. four cores with hyperthreading) so CPU time should theoretically improve.

The other component to look at would be adding memory to the system so it has the full compliment that the motherboard can handle — 32GB’s. The additional memory would be useful for the large sort used in the benchmark as well as adding another 4GB to 8GB of memory to the level 1 cache.

Finally, the other enhancement that I’m loathe to do is overclock the CPU. I don’t think that’s a worthy exercise because how often do you see a corporate workstation over clocked? I’ve never seen one to be honest.

One issue that I did not mention in the previous blog posts is the advantage gained by using a Level 1 Cache like FancyCache and using SSD’s. By using FancyCache, I reduced the hits and the wear-and-tear on the SSD’s. If I don’t have to write to the SSD’s and can instead use the Level 1 Cache, my investment in Solid State Disks should last longer.

About the author: Phil Rack is President of MineQuest, LLC. and has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and a reseller of WPS in North America.

Adventures in Porting

We’ve been busy porting the new version of the Bridge 2 R over to both the Mac and Linux platforms from Windows. The Windows release of the Bridge always allowed for the use of the Bridge from within the Eclipse Workbench. WPS didn’t have the Workbench as the GUI on the Max or Linux until version 3 which is the latest release. So, here’s what I found porting a large program that has to talk to different operating platforms (i.e. calls to the OS) for such things as delete files, move files, copy files, read directories, etc… and still interface with R.

The mundane part of porting was converting a lot of “\” to “/” throughout the code. In retrospect, we could have done a better job writing the Bridge in the first place to accommodate these conventions, but we didn’t have the intention of porting code back then either.

Here’s a couple of the gotcha’s that we experienced. When you read a directory on Linux or OS X, the structure is slightly different between the two and you have to accommodate that issue. The other BIG issue is that the pathnames are much longer on Linux and OS X when reading and writing to the WPS work folders. We ended up resizing our string variables to handle that specific difference.

The above might sound trivial but one think we discovered is that when you restart your server on OS X and Linux, the new work folder is contained inside the previous folder. For example, your original folder, let’s call it work1 is now hosting work2, your new folder. Now the path name is /work1/work2. But in reality, the names of the work folders are not work1 or work2 but long strings that can be hundreds of characters long. If you have a user who likes to restart their WPS Server, you can eat up a lot of string space quickly.

Since we store a lot of metadata for the Bridge 2 R inside the work folder, R has to be able to cope with very long filenames and I’m not convinced that it really copes all that well. Speaking of file names, here’s another anomaly between Windows and Linux/OS X systems. if you have a filename such as “myfile.txt ” (note the blank space at the end of .txt) Windows handles that just fine. Windows will interpret that as meaning you wanted “myfile.txt” However, if you write such a file or try to read a file with that name under Linux or OS X, then those two names are distinctly different. On Ubuntu or Fedora, that name shows up as “myfile.txt\” when you list the files from the terminal.

It took us about three days to port the Linux version of the Bridge over from Windows. Much of that time was spent dealing with the issues in the previous paragraph. We then took the ported Linux code and tested it on OS X. It took about 20 minutes to modify the section dealing with the difference in reading directories between the two platforms, and we then had a new version of the Bridge to R running on OS X.

In retrospect, porting the code over to Unix/Linux systems was worth the effort. It took a few days for us to do the porting and much of that was due to being naive about the new ported destinations. I will talk soon about the new enhancements (and a programming change users will have to make) in the Bridge to R in my next post.

About the author: Phil Rack is President of MineQuest, LLC. and has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and a reseller of WPS in North America.

Printing in WPS V3

The new version of WPS (version 3) is out and available and everyone has been busy sending out new license keys for this release. In our previous blog post, I presented some of the highlights of this release but want to talk about enhanced printing ability in V3.

The rendering of each page is a bit different than what you are previously used to in V2.5.x. You can see the difference in how the page is rendered in the screen shot below.

Notice the page breaks between the pages. One delightful aspect of this enhancement is that when you change line size settings in your programs, the page that is rendered reflects this. This is really great! The ability to print the reports from the Eclipse Workbench are also much improved.

One thing to be mindful of is that the options Orientation=landscape || Portrait is not supported. This isn’t that much of a big deal as you might at first expect. I simply set my LS=132 and PS = 45 and on my  printer properties for the print driver (a Canon MF-4150), I have a form called WPSDuplex_LS for duplex landscape mode. I can set the font for this print job automatically when I use this form. The font I use is Courier 9pt. This works like a charm for me.

Evaluations

MineQuest is offering free 30 day evaluations of WPS V3. You can contact us at (614) 457-3714 to request an evaluation or by email. If you prefer to request your evaluation by email, send a request to info@minequest.com.

About the author: Phil Rack is President of MineQuest, LLC. and has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and a reseller of WPS in North America.