Safe functions for casting numbers and timestamp in Oracle SQL

In the process of importing data which can be irregular from a flat file it is convenient to import all values as character strings, in this case Oracle’s varchar2, and then cast them into the proper format using the built-in datatype converters as e.g. to_number. The problem occurs when some value which is not convertible is stored in the column. This could be either because table column-overflow in the import process or because the value is optional and may be null or other non-set value. In this case the import methods doesn’t work.

Here are two methods I find useful for solving these problems, resulting in two PL/SQL functions embedding the functions used by oracle, but with a controlled exception where null values are stored and the error logged. Working on tables with several million rows I find this approach more useful than halting the process.

Safe number converter

CREATE OR REPLACE FUNCTION
safe_to_number (p varchar2)
RETURN number
IS
retval number;

BEGIN
IF p IS NULL THEN
retval := null;
ELSE
retval := to_number(p);
END IF;
return retval;

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Could not change value to number');
retval := null;
return retval;

END;

 

 

Safe timestamp converter

create or replace function safe_to_timestamp
( p_str in varchar2
, p_mask in varchar2)
return timestamp
is
d date;
begin
d := to_timestamp(p_str, p_mask);
return d;
exception
when others then
DBMS_OUTPUT.PUT_LINE('Could not change value to timestamp');
return null;
end;

 

I use these after the tables are imported as straight string-tables, to create a copy, but with the correct data format.

CREATE TABLE formatted_table as
SELECT
safe_to_timestamp(playdatetime,'YYYY-MM-DD HH24.MI.SS.FF') playdatetime,
safe_to_timestamp(dateval,'YYYY-MM-DD HH24.MI.SS.FF') dateval,
safe_to_number(id_table) id_table
FROM unformatted_table;

 

 

Sanntid hjemme: Følg Ruter hjemmefra med Arduino og Python

Sanntidsskjermene som Ruter har satt opp ved flere t-bane, trikk og bussholdeplasser har blitt et kjærkomment bidrag til informasjonen du som reisende får om avganger. Ikke bare kan du ha stålkontroll over hvilke avganger som går, og i hvilken rekkefølge, du blir også oppdatert om estimert ankomsttid slik at du vet at du mista bussen du løp for å rekke eller om bussen har blitt forsinka i rush-trafikken.

I tillegg til skjermene på holdeplassene som opplyser om sanntid, kan du få tak i app-er til mobiltelefonen og du kan også se dataene på forskjellige tredjepartsløsninger som f.eks på informasjonsskjermene ved Instiutt for informatikk ved Universitetet i Oslo. At dataene kan vises på mange forskjellige steder er mulig siden Ruter legger ut all ruteinformasjon til fri bruk (noen restriksjoner gjelder) på nettet. Det er dette vi kan benytte oss av når vi skal lage vårt eget sanntidssystem.

Informasjonsskjerm med sanntidsinformasjon

Vårt ferdige produkt vil være et sanntidssystem, ikke ulikt det man kan finne på holdeplassene. Selvsagt blir vårt produkt mindre robust og pålitelig, men i prototypings-fasen er dette helt greit. Skjermen skal vise hvilken linje neste avgang gjelder, hvilket navn det er på denne linjas endestasjon og hvor mange minutter det er til ankomst/avgang. For å få til dette benytter vi oss av en “dum” skjerm og av programvare som skriver teksten til denne. Skjermen vi bruker kobler vi til datamaskinen igjennom et Arduino grensesnitt. Vi bruker datamaskinen for å gjøre det meste av jobben, og vi legger mest mulig kompleksitet hit.

Informasjonsskjermen

Arduino er et veldig bra sted å begynne for å lære elektronikk, og hvordan vi kan kombinere dette med datamaskiner. Arduino har mange pedagogiske resursser tilgjengelig, og er laget for å være enkelt å komme igang med samt fleksibelt nok til å kunne skreddersys med egne komponenter.

Alle komponentene vi trenger følger med i Arduino innførings-pakke (Starter Kit). Vi tar utgangspunkt i oppgave 11, hvor vi skal lage en krystall-kule. Vi benytter oss av skjema-tegningene for å koble en LCD-skjerm til Arduino-brettet.

På Arduinobrettet laster vi opp følgende Sketch:

#include

LiquidCrystal lcd(12,11,5,4,3,2);

char a;

void setup() {
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.print("Ready for");
  lcd.setCursor(0,1);
  lcd.print("duty!");
}

void loop() {
  while (Serial.available() > 0 ){
    a = Serial.read();
    if (a == '!') {
      lcd.clear();
      lcd.setCursor(0,0);
    } else if (a == '?') {
      lcd.setCursor(0,1);
    } else {
      lcd.print(a);
    }
  }
}

 

 

Ardino-editor
Arduino-editoren

Vi benytter oss av LiquidCrystal biblioteket som følger med Arduino for å gjøre det enklere å skrive til brettet. Vi setter opp en Seriell-forbindelse og skriver en velkomstmelding til LCD-skjermen. Når LCD-skjermen er initialisert er det i hovedsak tre metoder vi benytter: print, clear og setCursor. Førstnevnte skriver en melding til skjermen, clear fjerner all tekst. setCursor benytter vi for å hoppe mellom skjermens to linjer. Metoden setCursor(0,0) setter skrivehodet øverst til venstre, og setCursor(0,1) setter skrivehodet til venstre i nedre rad.

Det er veldig lite kompleksitet på dette nivået, det eneste vi ønsker å gjøre er å kunne skrive, flytte mellom linjene og fjerne all tekst fra skjermen. Så lenge det er data i seriell-bufferet leser vi et tegn, og skriver dette til skjerm med mindre det er et spesialtegn. For dette programmet er “!” og “?” definert til å ha spesielle funksjoner. Utropstegnet fjerner all tekst og resetter skrivehodet til øvre venstre posisjon, spørsmålstegnet flytter skrivehodet til nedre venstre posisjon.

Skrive til skjerm

Når LCD-skjermen er satt opp og Arduino-koden er lastet opp kan man skrive til skjermen. Bruk CoolTerm (kan lastes ned her) og koble denne til Arduinobrettet (la brettet være koblet til via USB porten). Nå kan du skrive tekst som dukker opp på skjermen, samt kontrollere at spesialtegnene fungerer. Fungerer det? Kult, la oss koble oss opp mot Trafikanten/Ruter.

Trafikkdata fra Ruter

Ruter har offentliggjort mye av sin reiseinformasjon, og de har lagt ut sanntidsinformasjonen i tillegg til reiseplanleggeren, avvik og mye annet snasent. Les mer på Ruter sine API-sider

Vi skal benytte oss av to datasett fra Ruter, først må vi finne vår stasjons-ID ved hjelp av en kommaseparert fil med oversikt over alle stasjonene. Denne semi-statiske filen har meta-data som vi trenger for å kunne finne riktig stasjon fra REST JSON sanntids-APIet.

Finne stasjons-ID

For å finne riktig stasjon gjorde jeg en pragmatisk avgjøre om å ikke parse CSV-fila med alle stasjons-IDene. Jeg bare åpnet fila i TextMate (som jeg benytter for å redigere kode), og søkte etter Blindern T som ligger i nærheten av både jobb og hjem. Jeg fant ut Blindern T sin stasjons-ID er: 3010360

Hente og parse trafikkinformasjon

Oversiktlig, men maskinlesbar JSON strøm. Alle data vi trenger
Oversiktlig, men maskinlesbar JSON strøm. Alle data vi trenger

Ved å gå til datapunktet for sanntidsinformasjon ved denne IDen får jeg en JSON strøm/fil tilbake med alle avanger fra denne stasjonen: Blindern datapunkt.

I denne strømmen får vi mange objekter med avganger, og alle avganger har masse data vi kan bruke. JSON strømmen er ikke lett å lese og forstå, men så er den heller ikke laget for mennesker. Jeg benytter programmet VisualJSON for å lese JSON-filer.

Visual JSON is a handy tool for getting a more human readable representation of the data in the JSON stream
Visual JSON er et praktisk verktøy for å gjøre JSON-strømmer mer menneskevennlige

I VisualJSON kan vi se hvilke verdier i hver oppføring vi ønsker å ta vare på. DestinationDisplay inneholder navnet på endestasjonen, og LineRef inneholder linjenummeret. Praktisk å ta vare på disse. I tillegg trenger vi å lese ExpectedArrivalTime som har et noe merkelig tidsformat: “/Date(1378070709000+0200)/”.

Se hele implentasjonen? Mot slutten av siden finner du scriptet som henter, bearbeider, mellomlagrer og sender dataene skjermen.

Bearbeiding av datoene

De fleste dataene for hvert avgangsobjekt er klare for visning, men når det gjelder datoene trenger vi å gjøre noen endringer. Formatet vi fikk disse i er vanskelig å forstå for mennesker. Datamaskiner kan enkelt regne ut hvor mange sekunder som har passert siden torsdag 1 January 1970 (tidsformatet Epoch time), men for mennesker er dette vanskeligere. Vi parser derfor epoch formatet til datetime, og i fra dette formatet finder vi time delta (tidsdifferansen) mellom når avgangen er forventet og nå. Når vi tar denne tidsdifferansen og gjør den om til minutter har vi antall minutter til avgangen som vises.

Mellomlagring av data

Jeg har valgt å lage en klasse som inneholder de nødvendige dataene for hver avgang. Objektene vi oppretter av denne klassen legger jeg inn i en liste, hvor jeg henter ut ett og ett element. Når lista er tom går jeg til nett-tjenesten for å hente nye data. Det er fint å slippe å gå til tjenesten hele tiden for å hente data, samtidig må vi også bli oppdatert på eventuelle forsinkelser eller dersom antatt ankomsttid skulle flyttes framover i tid. Jeg syntes at å lagre alle avgangene i en kø for så å hente nye data når denne er tømt er en god løsning på denne utfordringen.

Formatere data for LCD-skjerm

For at dataene skal vises riktig må vi formatere de. Måten jeg har valgt å gjøre dette på er ved å lage setninger for hver linje. Altså først sende en melding om at skjermen må tømmes og resettes, deretter øverste linje med linjenummer og endestasjonsnavn. Når dette er sendt, venter jeg 0.2 sekund før jeg sender linjeskift-kommandoen (“?”), og linje nummer to. Jeg venter 0.2 sekunder mellom hver melding for å ikke mate skjermen med for mye informasjon samtidig. Når all tekst vises lar jeg denne stå i 4 sekunder før jeg går videre til neste avreise.

Implementasjon av programvaren

Nedenfor finner du hele scriptet som henter data fra Ruter, og som sender dette til Arduinobrettet

import urllib2, json, datetime, re, serial, time
from pprint import pprint

class TrafficInfo:
  def __init__(self, line_ref, destination, arrival_minutes, monitored, platform):
    self.line_ref = line_ref
    self.destination = destination
    self.arrival_minutes = arrival_minutes
    self.monitored = monitored
    self.platform = platform


def days_hours_minutes(td):
  return td.days, td.seconds//3600, (td.seconds//60)%60

def fetchTrafficFromStation(station_id):
  url_loc = "http://reis.trafikanten.no/reisrest/realtime/getrealtimedata/%s" % station_id
  response = urllib2.urlopen(url_loc)
  data = response.read()
  return data

station_id = "3010360"
ser = serial.Serial("/dev/tty.usbmodemfa131", 9600)
arr = []

while(True):
  if len(arr) == 0:
    print "Fetching new data"
  data = json.loads(fetchTrafficFromStation(station_id))

  for el in data:
    timecode = el["ExpectedArrivalTime"]
  m = re.split("(\d{13})\+(\d{4})",timecode)
  dt = datetime.datetime.fromtimestamp(float(m[1])/1000)
  tn = datetime.datetime.now()
  d = dt - tn
  td_human = days_hours_minutes(d)
  minutes = False
  if (d.seconds < (3600 - 1)): minutes = td_human[2]
    ti = TrafficInfo(el["LineRef"], el["DestinationDisplay"], minutes, el["Monitored"], el["DeparturePlatformName"])
  arr.append(ti)

  time.sleep(1)
  ar = arr.pop(0)
  time.sleep(1)
  ser.write("!")
  time.sleep(0.3)
  over_str = "%s : %s" % (ar.line_ref,ar.destination)
  ser.write(over_str)
  time.sleep(0.3)
  ser.write("?")
  time.sleep(0.3)
  under_str = "%s %s" % (str(ar.arrival_minutes), "Minutes")
  ser.write(under_str)
  time.sleep(4)

 

 

Du trenger ikke nødvendigvis en LCD-skjerm for å hente trafikkdata fra Ruter, og du trenger ikke nødvendigvis å vise trafikkdata dersom du har en LCD-skjerm. Det er bare fantasien som setter grenser. Hva med for eksempel værdata fra yr.no, eller temperaturen i kjøleskapet? Arduino er et flott sett for å leke med noen av mulighetene elektronikk og informatikk gir deg.

Appropos Arduino: I forrige uke var jeg med på en workshop med Tom Igoe, som har skrevet boken Making things Talk. Jeg har selv ikke lest denne boka, men har hørt at den er en god kilde til kunnskap og inspirasjon. Check it out!

Create an online webservice fast with Sinatra and Heroku

So you want to explore the posibitilies of the web, and you want to look the static HTML files served from a web server. Here is a short introduction to how you get a dynamic webserver up and running as fast as it gets utilising the Sinatra web-framework and the hosting provider Heroku. Heroku has already have gained cred in the developer society, and Facebook is now recommending Heroku as PaaS (Platform as a Service) when you create services. It is super-easy to get started, and comes with lots of instant gratification.

Heroku_serious_mem

Sinatra and Rails

Sinatra is a lightweight web-framework using Ruby with Rack. I have earlier looked at Ruby on Rails, which is also a great framework based on the same platform. The main difference is the complexity of the two systems. Rails comes with a great Model-View-Controller structure, database mapper and lots of neat stuff, but sometimes you just want simplicity, and Sinatra got simplicity written all over. Yes, you may do a lot of advance things in Sinatra, and you can make something really simple in Rails, but why not harness the nature of these two frameworks. If you are going to make something complex and wants a strict convention-over-configuration approach go for rails, if you just want something really simple, clean and clear let’s get started with Sinatra.

Installation

I expect you to have ruby and it’s gem package version system installed. If not you will have to install these. I would recommend you to also look into RVM, so that you can have more ruby versions installed with their gems, and in this manner retain the software versions of your platform and gems when you upgrade other applications.

All you have to do is download the package ‘sinatra’. Just “gem install sinatra” into your shell and et voila. You now have installed Sinatra. You can verify this by opening the ruby in an interactive shell with the command ‘irb’, and then require the package “require ‘sinatra'” in the irb-terminal.

You will also need to install heroku. The process is as easy as installing sinatra. Just type “gem install heroku” into the shell.

You would also need to install git – the version controll system – and sign up for Heroku.

Installing Git

The version control system system Git is gaining a lot of momentum. The website Github is based around git, and Heroku uses it for pushing local files to the web server. A fun fact: Git has also inspired a TED speech by Clay Shirky. You can download Git from here.

Sign up for Heroku

Just like installing Git is easy, signing up for Heroku is even easier. Sign up through Heroku’s website and follow the instructions. You will also need to download a heroku gem which makes interaction through the terminal quick and easy.

You also need to create a pair of SSH-keys and exchange these with the server for authentication when you are uploading files. Here you find a tutorial for creating the keys.

Creating a Sinatra application skeleton

What makes Sinatra a very convenient tool is how lightweight it is, and still expendable. When you start you only need a couple of files, and from there you expand the application to accomodate the level of complexity you need. I like to use Sinatra with dead simple small applications.

To begin creating a Sinatra app, first create an empty folder. I use the computers Command Line Interface to use this (on a Mac this is called Terminal and can be found in the Utility folder). You can create a new folder by using mkdir command with the name of the folder-to-be as the only argument: ‘mkdir myfirstsinatraapp’

Navigate into this folder by using the cd command. For the most convenient *nix commands please see this introduction.

Put the Sinatra application under Git version control

In the folder, initialise git with the command “git init”. You now have an empty git repository.

Create the app

The only thing you will need to begin with is a config.ru, Gemfile file and an app.rb file. An easy way to create these are with the “touch filename” command where filename is the name of the desired file.

In the config.ru file, require the app.rb file, and call the “run Sinatra::Application” command. The file should look like this:

[sourcecode language=”ruby”]
require ‘./app’
run Sinatra::Application
[/sourcecode]

The other file you would need to create is the app.rb. This file would act as your main file for your application. Where you can generate routes and fill them logic.local

At the top of the file, require sinatra and create a route to the index path:

[sourcecode language=”ruby”]
#!/usr/bin/env ruby
#encoding: UTF-8

require ‘sinatra’

get ‘/’ do
"Hello world"
end
[/sourcecode]

The ‘/’ represents the root of your web-app, and once you go to this page you will be prompted with the text “Hello world”. Don’t take my word for it, try it yourself.

You will also need a Gemfile, in which you list the gems used by your application and where to get them. Since our application is super-simple we only need to list Sinatra. After writing and saving the gemfile. Install the gems by typing ‘bundle install’.

[sourcecode language=”ruby”]
source ‘https://rubygems.org’
gem ‘sinatra’
[/sourcecode]

In the folder with your files, type “ruby app.rb“, this will start a web-server with your application. The default location is localhost:3456, but this will be prompted in the terminal. Open a web browser, and type in the address and port-number to your web-server. You should now see the plain text “Hello world”.

A very simple output
A very simple output

Commit and push your application to Heroku

To publish your application to Heroku you will need to add all files to the empty git repository we created above. Add all files with the command “git add .” (The dot represents the current directory). Check that all files are staged with “git status“. Commit the changes with “git commit -m ‘wohoo. going live’ “.

Now, all the code is in the git repository and ready to be uploaded to Heroku. Write “heroku create” into the shell. After the command is executed a URL to your service on heroku should have been created and displayed by the command, the command should also have created a remote repository in your git file. This is transparent to you as a user, but you can verify by typing ‘more .git/config’. A line with ‘[remote “heroku”]’ and a couple of lines under this should have been added.

When this is done, you are ready to push your code onto Heroku. Type ‘git push heroku master‘ to make your local code available from the internet. As you add files and alter code, add these to the git, commit and push them to Heroku.

Screenscrape av Øya-programmet

Forskningsprosjektet Sky & Scene, hvor jeg jobber, ser blant mye annet nærmere på strømmetallene fra WiMP før, under og etter Øya-festivalen. For å gjøre dette trenger vi en liste over hvilke artister som spiller, hvilken dag de spiller og når på dagen de spiller. Før dataene kan analyseres må disse dataene være tilgjengelige i Excel-ark og i CSV-format og i databasen hvor strømmetallene finnes. Dataene må hentes og struktureres i et bestemt format.

Et godt utgangspunkt er å samle dataene i et CSV-format. CSV står for Comma separated values, kommaseparerte verdier, og er en liste hvor verdiene er for en forekomst er samlet på en linje, og hvor forekomstens data-attributter, også kalt variabler, er separert med – you guessed it – komma. Et lignende format kan du finne i Excel hvor èn forekomst finnes på èn linje, og denne forekomstens variabler oppgis i kolonner.

Finne dataene

Ok, nok om formatering. Hvor kan vi finne dataene? Et naturlig utgangspunkt er festivalens hjemmesider. På oyafestivalen.com (den engelske hjemmesiden til festivalen) finner vi et menyvalg kalt “program“, og her finner vi også programmet.

developer_menu_oyafestival
Utviklerverktøyet til Chrome kan finnes i menyen. Dette er et veldig nyttig verktøy for både web-utvikling og screen scraping

For å screen scrape programmet hjelper det lite med den visuelle presentasjonen av siden og vi må derfor se på HTML kilden. I Google Chrome finner du denne ved å høyreklikke i web-vinduet for så å klikke på “vis sidekilde”, her kan vi finne HTML-koden. Eventuelt kan du kopiere denne lenken inn i din Chrome browser: “view-source:http://oyafestivalen.com/program/#all

Dersom du gikk inn i kildekoden vil du se at listen med artister mangler. Hvorfor? Jo, fordi listen er ganske lang og benyttes av flere kilder lastes ikke listen med programmet inn av selve program-siden. Den lastes inn asynkront med AJAX (Asynchronous Javascript and XML). Finn fram Chrome Developer Tools som finnes i menyen, og gå til Network fanen. Last siden igjen ved å klikke på sirkelen med pil til venstre for URL-feltet.

Her kan du se at en fil kalt getArtist.php er lastet (bilde 1), og at denne filen ikke lastes som en del av originalforespørselen vår til web-tjeneren, men istedet er lastet inn via Javascript. Dersom vi klikker for å se på hva denne URL-en leverer kan vi se at artistlisten kommer herifra. URLen til siden kan du finne ved å høyreklikke på navnet getArtist.php og så velge “copy link address”.

Når du har URLen (http://oyafestivalen.com/wp-content/themes/oya13_new/includes/ajax/program/getArtists.php) kan du kopiere denne inn i nettleser vinduet ditt. Du skal nå få en liste uten spesiell formatering som ser omtrent slik ut:

artistliste_oyafestival
Øyafestivalens artistliste hentes fra serveren asynkront for å spare tid når hovedsiden lastes. Nå har vi funnet dataene vi trenger.

OK, nå har vi funnet dataene vi trenger. Nå må vi bare finne en god måte å hente de ut fra siden. La oss ta en titt på kilden bak konsertlista. Her finner vi både dataene og strukturen vi trenger:

Dataene vi trenger, men med en annen formatering. Uansett, nå gjenstår bare hentingen og reformateringen.
Dataene vi trenger, men med en annen formatering. Uansett, nå gjenstår bare hentingen og reformateringen.

Her kan vi se at:

  1. Ytterst har vi en div-tag med klassen “table title”. Denne innleder forklaringen som står over kolonnen i visningen.
  2. Vi har en uordnet liste (ul-tag) med klassen “table”
  3. Den uordnede listen har flere barn som er satt i liste elementer (li). Disse benytter seg av HTML5 data-attributter, men disse skal vi ikke bruke i denne omgang.
  4. Hvert liste-element har et span element med klassen “name”, hvor innholdet er navnet på artisten
  5. Liste-elementet har også en klasse “scene” med scene navnet som innhold.
  6. Sist har liste-elementet også en “date” klasse med de tre første bokstavene på dagen, tre non breaking spaces (HTML syntaks: &nbsp;) og tidspunkt for konsert-start.

Her finner vi alle dataene, og formateringen er også lik for alle elementene i lista med klassen “table”.

Når vi nå har funnet datakilden kan vi begynne å trekke ut dataene for videre bruk.

Screen scrape med Ruby og Nokogiri

Vi har nå funnet kilden og da kan vi benytte oss av Ruby og biblioteket (ruby-term: gem) Nokogiri.

Før vi begynner å hente dataene må vi gjøre klart scriptet som skal hente dataene fra festivalens hjemmeside. Vi inkluderer nokogiri som skal hjelpe oss å parsere datakilden. Samtidig laster vi også inn csv-bibliotek for å skrive ut filene og open-uri for å kunne lese URI-kilden som en fil.

[sourcecode language=”ruby”]
#!/usr/bin/ruby
# -*- encoding : utf-8 -*-

require ‘nokogiri’
require ‘open-uri’
require ‘csv’
[/sourcecode]

Konsert klassen

For å lagre og manipulere dataene lager vi en klasse for å lagre de fire verdiene vi trenger: artist, scene, date og datetime. Hos kilden finner vi de tre første verdiene og datetime konstruerer vi utfra date.

For klassen setter vi alle variablene vi skal benytte med en attr_accessor. Dette gjør at ruby selv genererer get og set-metoder for alle variablene listet etter funksjonen, noe som gjør at vi fritt kan hente og sette variablene fra instansene av klassen.

Vi skriver en initialize-metode, en konstruktør, som kalles når instansen opprettes. Siden vi allerede henter artist, scene og dato fra datakilden kaller vi konstruktøren med disse variablene slik at disse settes. For å oversette date til datetime, lager vi en dictionary med dagene og tilsvarende ISO-datoformat.

Legg merke til at når instans-variabelen @date settes, så gjøres det en del formatering. Fra kilden får vi datoformatet noe annerledes, så vi fjerner non-braking space, og bytter ut punktum med semikolon og sørger for at det er mellomrom mellom de tre bokstavene som angir dagen, og klokkeslettet. Når dette er gjort kaller vi en metode for å generere datetime-verdien basert på date-verdien. Vi bruker @ foran variabelnavnet for å markere at dette er en instanse-variabel.

metoden add_datetime gjør et oppslag i date_dict og bytter ut dag-bokstavene med ISO-dato, deretter henter den ut tidspunktet fra @date variabelen og interpolerer disse to verdiene til en datetime string.

Den siste metoden vi lager to_arr tar alle instanse-variablene og returnerer disse som en array. Siden CSV-funksjonen vi inkluderte tidligere kan lage en CSV-linje fra en array er dette en hendig måte å hente ut verdiene fra objektet.

[sourcecode language=”ruby”]
class Concert
attr_accessor :artist, :scene, :date, :datetime
def initialize(artist, scene, date)
@date_dict = {‘wed’ => ‘2013-08-07′ ,’thu’ => ‘2013-08-08′ ,’fri’ => ‘2013-08-09′ ,’sat’ => ‘2013-08-10’}
@artist = artist.strip
@scene = scene.strip
@date = date.gsub(/\u00a0/, ”).gsub(‘.’,’:’).gsub(/([a-zA-Z]{3})(.)/,’\1 \2′).strip
self.add_datetime
end

def to_arr
return [self.artist, self.scene, self.date, self.datetime]
end

def add_datetime
@datetime = "#{@date_dict[@date[0,3].downcase]} #{@date[4..9]}"
end

end
[/sourcecode]

Lese dokumentet, hente ut dataene og lage objektene

Når vi nå har en datastruktur hvor vi kan lagre informasjonen, kan vi begynne å hente informasjonen fra internett. Aller først lager vi igjen en tom dictionary hvor vi ønsker å lagre våre konsert-objekter etterhvert som vi lager disse.

Vi bruker Nokogiris HTML klasse og lagrer denne til doc variabelen. Til denne sender vi en tekst-strøm som hentes fra URLen. Vi sender altså samme tekst som vi fikk fra getArtist.php kildekoden til Nokogiri.

Nokogiri har en utmerket methode kalt css. Denne metoden tar en CSS (Cascading Style Sheet) selektor og finner riktig element fra DOMen (Document Object Model) som Nokogiri holder. Vi ønsker å iterere over alle “.table li”-nodene (alle li-nodene under table-klassen), og gjør dette ved enkelt med .each metoden.

For hver “.table li” vi itererer over, henter vi ut innholdet av elementene som har klassene .name, .scene og .date og oppretter et objekt av Concert-klassen. Det siste vi gjør for hver iterasjon er å lagre objektet med artisten som nøkkel i vår concerts dictionary.

[sourcecode language=”ruby”]
concerts = {}

doc = Nokogiri::HTML(open(‘http://oyafestivalen.com/wp-content/themes/oya13_new/includes/ajax/program/getArtists.php’))
doc.css(‘.table li’).each do |el|
a = Concert.new(el.css(‘.name a’).first.content,
el.css(‘.scene’).first.content,
el.css(‘.date’).first.content)
concerts[a.artist] = a
end
[/sourcecode]

Printe objektene som CSV

Når vi har opprettet alle objektene ønsker vi å skrive ut alle variablene i disse til fil. Vi gjør dette ved å åpne en fil kalt output.csv med skrivetilgang. Deretter itererer vi igjennom alle objektene og bruker nøkkelen fra k-variabelen til å hente ut hvert enkelt objekt som finnes i vår concerts dictionary. For å kun få Øya-festivalens konserter (ikke klubb-Øya) sjekker vi at konserten fant sted på enten scenene “Enga”, “Klubben”, “Sjøsiden” eller “Vika” (Sjøsiden har feil format her som vi senere korrigerer i Excel). For hvert objekt hvis scene er inkludert blant Øya-scenene skrives det en linje til csv-fila som tar en array med verdier. Denne arrayen hentes fra to_arr metoden vi skrev i Concert-klassen.

[sourcecode language=”ruby”]
CSV.open("output.csv", "wb") do |csv|
concerts.each do |k,v|
csv << concerts[k].to_arr if [‘Enga’,’Klubben’,’Sjøsiden’,’Vika’].include? concerts[k].scene
end
end

[/sourcecode]

Sånn. Nå burde du ha en CSV med alle Øya-artistene som du kan enten importere til en database eller åpne i Excel.

Hele scriptet:

[sourcecode language=”ruby”]

#!/usr/bin/ruby
# -*- encoding : utf-8 -*-

require ‘nokogiri’
require ‘open-uri’
require ‘csv’
require ‘open-uri’

class Concert
attr_accessor :artist, :scene, :date, :datetime
def initialize(artist, scene, date)
@date_dict = {‘wed’ => ‘2013-08-07′ ,’thu’ => ‘2013-08-08′ ,’fri’ => ‘2013-08-09′ ,’sat’ => ‘2013-08-10’}
@artist = artist.strip
@scene = scene.strip
@date = date.gsub(/\u00a0/, ”).gsub(‘.’,’:’).gsub(/([a-zA-Z]{3})(.)/,’\1 \2′).strip
self.add_datetime
end

def to_arr
return [self.artist, self.scene, self.date, self.datetime]
end

def add_datetime
@datetime = "#{@date_dict[@date[0,3].downcase]} #{@date[4..9]}"
end

end

concerts = {}

doc = Nokogiri::HTML(open(‘http://oyafestivalen.com/wp-content/themes/oya13_new/includes/ajax/program/getArtists.php’))
doc.css(‘.table li’).each do |el|
a = Concert.new(el.css(‘.name a’).first.content,
el.css(‘.scene’).first.content,
el.css(‘.date’).first.content)
concerts[a.artist] = a
end

CSV.open("output.csv", "wb") do |csv|
concerts.each do |k,v|
csv << concerts[k].to_arr if [‘Enga’,’Klubben’,’Sjøsiden’,’Vika’].include? concerts[k].scene
end
end

[/sourcecode]

Descriptive Statistical Methods in Code

Statistics can be mighty useful, and a little programming helps it getting even better. I often find that I through code can grasp the fundamental function behind how things work, and I have tried to apply this to statistics as well. In this case to descriptive statistics.

Join me in this short attempt to let statistics unconceal itself.

Getting ready: Extremistan and Mediocristan

This little text is looking closer on some of the descriptive methods of statistics, and to do that I want to use proper dataset. I have collected two data-sets following two different paradigms. The first dataset follows the rule of normal distribution/bell curve, derives from the physical world and is little susceptible to what Nassim Nicholas Taleb has identifies as the domain of Black Swans. In Mediocristan values seldom deviates, and when they do it’s not extremely.

On the other hand, our second dataset is from the social world where values does not conform to the bell curve, and where single values may change the whole dataset. In the domain of Extremistan values found includes many from the socio-cultural domains including number of cultural items sold, wealth, and number of Twitter followers.

Hights of 10 people  = 176, 182, 170, 186, 179, 183, 190, 183, 168, 180

Wealth of 10 people (imagined denomination) = 20, 100, 15, 5, 100, 10000, 1000, 30,  5, 200

To compute upon our values, we will save them into arrays.

[sourcecode language=”python”]

heights = [176, 182, 170, 186, 179, 183, 190, 183, 168, 180]
wealth = [20, 100, 15, 5, 100, 10000, 1000, 30, 5, 200]

[/sourcecode]

The count

This method is as simple as it gets. The count does not look at any of the numeric value stored, it just count the number of occurrences. In Python we have the comprehensive method len() to which we can pass the array and get returned the length.

[sourcecode language=”python”]

def count(data_arr):
return len(data_arr)

[/sourcecode]

The sum

To find the sum of the elements, we need to look in on the values and add these together. This is done by iterating through all the elements and add the value of all the elements to a single variable which we then return. Python has already a sum method implemented which does exactly what we need, but instead of using this we make our own: ownsum

[sourcecode language=”python”]

def ownsum(data_arr):
i = 0
for val in data_arr:
i += val
return i

[/sourcecode]

The min

All the values we have in both our arrays are comparable, the height is measured in centimetres and the wealth in a denomination. A higher number refers to more, and a lower number to less of that measure. The min, or minimum, finds the smallest value and returns this. To do this we need to start with the first number and always retain the smallest value we iterate over. In the implementation below the start value is set to the maximum value available to the system. To get this value will need to import the sys (system) library. Python already have a min method, so we implement our own: ownmin.

[sourcecode language=”python”]

import sys

def ownmin(data_arr):
i = sys.maxsize
for val in data_arr:
if val < i:
i = val
return i
[/sourcecode]

The max

The max method is somewhat a reversed min method. It looks at all the values and find the largest number. To get here we need to always retain the largest number as we iterate over the array. We start with the smallest possible value and then iterate. The max function is already implemented in Python, so we write our own: ownmax

[sourcecode language=”python”]

def ownmax(data_arr):
i = -sys.maxsize
for val in data_arr:
if val > i:
i = val
return i

[/sourcecode]

The range

The range is the numerical difference between the smallest and the largest value. This can give us a quick indication on the speadth of data. The range is fairly easy to find using subtraction. If we subtract the min from the max we are left with the range. We could write a whole function first performing the calculations for min and max and then do the subtraction, but since we already have implemented our own ownmin and ownmax methods, why not take advantage of our work already done. Python already has a function named range, so to avoid namespace problems let us implement the method ownrange

[sourcecode language=”python”]
def ownrange(data_arr):
return ownmax(data_arr) – ownmin(data_arr)
[/sourcecode]

The mean/arithmetic average

The mean, or the arithmetic average tells us something about the central tendency. The mode and the median average does so as well, but where the mode looks at occurrences and median look at the central element in an order list, the arithmetic average takes the sum of all elements and divide on the count. This is the most common way of finding the central tendency, but it is also prone to misunderstand large deviations in the dataset.

[sourcecode language=”python”]
def mean(data_arr):
return ownsum(data_arr) / count(data_arr)
[/sourcecode]

The median average

For the median average the values of each element is less importance, the paramount here is the position at where the elements can be found in relation to each other. The median is basically the middle element of an sorted array. If the array has an even number of elements the median is the aritmetic average of the two middle values. In the implementation of the method we first sort the array, then we get the length. If the length of the array is divisible by two (even number of elements) we return the average of the two middle values, if not we return the value of the middle element.

[sourcecode language=”python”]
def median(data_arr):
sorted_arr = sorted(data_arr)
length = len(sorted_arr)
if not length % 2:
return (sorted_arr[length / 2] + sorted_arr[length / 2 – 1]) / 2.0
return sorted_arr[length / 2]
[/sourcecode]

The mode average

The mode average is the most frequent value of the dataset. In our case this may not be representative, but if you have large datasets with many datapoints it makes more sense. The mode can be used trying to identify the distribution of the data. Often we have a mental anchor of the dataset having a unimodal distribution with a central peak with the most frequent occurrences of values in the centre and descending frequencies as we move away from the centre in both directions (e.g. the Empirical rule and bell curves), but datasets can also be bimodal with two centres towards each end of the spectre and few frequencies towards the centre. In a large dataset, the mode can help us spot these tendencies as it allows for more mode averages. For example a dataset with a range from 10 to 30 may have a unimodal distribution with a mode at 20, but also have a bimodal distribution with a mode at 15 and 25, this would be hard to spot for both the median and arithmetic averages.

To find the mode we need to create a dictionary. In this dictionary we create a key for each of the distinct values and a frequency of these. Once we have the dictionary, we need to iterate this to find the most frequent values. A mode can consist of more values, so we need to check the value of all the dictionary items against the max number of frequencies and return the element, or all elements that has this number of occurrences. Be aware that if none of the distinct values have more than one occurrences, all occurrences are returned.

[sourcecode language=”python”]
def mode(data_arr):
frequencies = {}
for i in data_arr:
frequencies[i] = frequencies.get(i, 0) + 1
max_freq = ownmax(frequencies.itervalues())
modes = [k for k, v in frequencies.iteritems() if v == max_freq]
return modes
[/sourcecode]

The variance of a population

The variance is used for finding the spread in the dataset. In the average methods above we found the central tendency of the dataset, and now we need to see how much the values of the dataset conforms to this number. For these values you can find whether you dataset is more extreme or mediocre (these are not binary groups, but gravitating centres). Once presented with an average from a dataset, a good follow up question is to ask for the standard deviation (next method). The variance is the sum of each values difference from the mean. To implement this method we first find the arithmetic mean for the dataset, and then iterate over all values comparing them to the average. Since the difference can be both higher and lower than the average, and we want to operate with positive numbers we square each value.

[sourcecode language=”python”]
def variance(data_arr):
variance = 0
average = mean(data_arr)
for i in data_arr:
variance += (average – i) **2
return variance / count(data_arr)
[/sourcecode]

The standard deviation

From the variance the way to the standard deviation is fairly simple. The standard deviation is the square root of the variance. This has the same measure as the average and is easier to compare. Here we take advantage of our last method and run a square root method on this to get the standard deviation. The sqrt method needs to be imported from the maths library. Be aware that standard deviation and variance is treated differently whether working with a sample or with a population. The differences is outside the scope of this article.

[sourcecode language=”python”]
import math
def stddev(data_arr):
return math.sqrt(variance(data_arr))
[/sourcecode]

The final code

We have now implemented some of the basic descriptive methods in statistics. The whole project can be found below. To run some of the functions. Call them by their method name and pass in an array. Two 10 elements long arrays can be found in the script, but the methods are implemented in such a way that you can pass with an array of any length.

[sourcecode language=”python”]

import sys
import math

heights = [176, 182, 170, 186, 179, 183, 190, 183, 168]
wealth = [20, 100, 15, 5, 100, 10000, 1000, 30, 5, 200]

def count(data_arr):
return len(data_arr)

def ownsum(data_arr):
i = 0
for val in data_arr:
i += val
return i

def ownmin(data_arr):
i = sys.maxsize
for val in data_arr:
if val < i: i = val return i def ownmax(data_arr): i = -sys.maxsize for val in data_arr: if val > i:
i = val
return i

def ownrange(data_arr):
return ownmax(data_arr) – ownmin(data_arr)

def mean(data_arr):
return ownsum(data_arr) / count(data_arr)

def median(data_arr):
sorted_arr = sorted(data_arr)
length = len(sorted_arr)
if not length % 2:
return (sorted_arr[length / 2] + sorted_arr[length / 2 – 1]) / 2.0
return sorted_arr[length / 2]

def mode(data_arr):
frequencies = {}
for i in data_arr:
frequencies[i] = frequencies.get(i, 0) + 1
max_freq = ownmax(frequencies.itervalues())
modes = [k for k, v in frequencies.iteritems() if v == max_freq]
return modes

def variance(data_arr):
variance = 0
average = mean(data_arr)
for i in data_arr:
variance += (average – i) **2
return variance / count(data_arr)

def stddev(data_arr):
return math.sqrt(variance(data_arr))

[/sourcecode]

Three Useful Terminal Commands

See my terminal-tools tag for more articles on nifty terminal tools.

The *nix terminal is a great tool. In everyday life this is where a lot of things can be done easy and fast with this power tool. There are an abundance of tools and ways of solving problems with the terminal, but here you have three practical applications.

Find a text string within current folder

grep your_magic_string -H -R *

The command ‘grep’ is used as a search tool for plain text files matching a regular expression. In the example above we want to find the string ‘your_magic_string’ within the current folder, so we want grep to search recursively as is done through passing with the option ‘-R’ and the wildcard (‘*’). This command will return all text files within the current folder where this text streng can be found. The -H option prints the filename.

Search and replace text within a file

sed -i 's/wrong/right/g' /home/ola/list-with-stuff/somethingwrong.txt

Sed is a stream editor that parses text and implements a programming language so that this text can be modified. The script above reads a file at the endmost location (‘/home/ola/list-with-stuff/somethingwrong.txt’) and searches through the file replacing the text pattern ‘wrong’ with ‘right’. The -i option overwrite the original file with the alterations. What used to be a negative text is now super positive.

Download a file from the Internet

curl -o http://http://www.lovholm.net/wp-content/uploads/2013/06/mega_secret.jpg megasecret.jpg

Curl is a nice tool to access resources on the Internet. If you want to see the source of a web-page just enter the URL after curl. For binaries and files you want to retain you can add the -o option. This lets you print the output to a file instead of displaying the text representation in your terminal window.

Bonus: Star Wars

All work and no play, makes ___________ (enter your name) a dull ___________ (enter your gender here). Bring popcorn, kick back in your chair and type the command: telnet towel.blinkenlights.nl. Enjoy!

Mac OSX

The mac terminal icon
The mac terminal icon

What many Mac OSX users doesn’t know is that the OSX is built on Unix. In the Utilities folder under Applications you will find a terminal.Through this application you can do lots of things quick and easy. A google search reveal many good tutorials

Note: If some of the commands above prompts and error message saying that the command is unknown, you would need to install the program. Use your local packet manager such as yum or apt-get to install these. On Mac macports is a nifty packet manager.

Image: The terminal can also be used for cool stuff such as surfing the waves of the internet. The picture shows the web browser Lynx. The terminal was after all the main mode of communication with the computer before the dawn of the Graphical User Interface, and is still widely used.

The Lynx Web browser displaying lovholm.net

Push your code onto your EC2 instance with Git

Here is a little thing that has saved me a lot of work, and which I find quite neat.

I use the EC2 as my cloud computer. This page (lovholm.net) is hosted on a shared host, but sometimes it’s nice to have the flexibility to run things that are not supported by shared hosts, such as custom software and all that jazz. When I try out different web-things that are not only front-end or PHP I usually create a subdomain and place the code on an EC2-instance after initial development on localhost.

Since I now use different environments for development I have found this neat way of pushing code  from my local computer to the server. This is a lot easier than using FTP, and is more flexible than deploying to Heroku (which is – by the way – a brilliant super-easy way of hosting and deploying).

The idea is very similar to that used by Heroku, except that the setup is more complex and the good terminal tool is lacking. On the other hand it gives you greater flexibility to run your own instance and it may also be more affordable if you plan to make your code into a business with much traffic.

Don’t know what git is, or don’t have git installed. Github has some great documentation on installation and Git on what git is.

Setting up the Git-repositories

Locally I initialise a git repository in the folder I am working.

local $ cd the-amazing-test-project
local $ git init

Then I use SSH to connect to my cloud computer where I have a folder for remote git repositories (I store these in a sibling-folder to the root folders of my projects.)

remote $ cd git-repos
remote $ mkdir testrepo.git
remote $ cd testrepo.git
remote $ git init --bare

When this is done, we need to create a remote-link from the local repository, and create a post-update hook at the remote repository. This will make you able to push the code from the local git-repo onto the server and from there unpack the code and do other neat things like logging and restarting of servers (if necessary).

The cloud instance as remote repository

So now you have a local repository on which you work, commit and track your local files, and you have a bare repository in the cloud. Let’s make the bridge.

local $ git remote add web ssh://ec2-user@yourwebserver.cloud.org/home/www/git-repos/testrepo.git

Create an empty file in the local directory, use

git add .

to add this file to repository, commit the changes to the git repository:

git commit -am "Initial test"

Now you could push the repository to the clouds using:

git push web master

If you get an error message. Make sure that you have added the keys used to connect to the remote host to your ssh-keys. If not, you could use ssh-add to do this. Call the command ssh-add with the key as the only argument.

If you still experience problems. Enter the local repository with your terminal and then change to the .ssh directory where you will find a file named config. This content of the file should be something similar to this:

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = false
[remote “web”]
url = ssh://ec2-user@yourwebserver.cloud.org/home/www/git-repos/testrepo.git
fetch = +refs/heads/*:refs/remotes/origin/*

Add a hook for deployment

Once you have a connection between the local and remote repository, we need to make a way for the remote repository to deploy our code and not just keep it safe and sound. Connect through ssh to the terminal of your remote computer and change into the git-repos directory and your testrepo.git folder.

Within this folder you should have a folder with hooks, and it is here we are going to add the last pieces of code to get our system up and running. We will utilize the server-side hook post-update to deploy our code and do other tasks needed. The post-update hook is a shell script which git executes after receiving a push. Add to this the following code:

#!/bin/sh
GIT_WORK_TREE=/home/www/amazing_web git checkout -f

echo "the_amazing_web_project checkin at: <$(date)> " >> /home/www/logs/updates_log

The second line in this code excerpt will extract the data (when adapting this snippet, make sure the path after the equal sign is created), and the fourth line will add to a logfile the name of the project and the date.

You can now commit code to your remote server easy, and if you need to do any changes like rebooting the web-server you can add the code to the post-update script.

The Raspberry Pi

The Raspberry Pi has been on the market for a while now, providing a very affordable, small computer for the computer interested and hobbyist hackers. The idea of the Raspberry Pi came in 2006 when teachers at the University of Cambridge’s Computer Laboratory became concern about the decline in numbers and skill-levels among the A-level students who entered computer science. The tinkers of the early computer generation were replaced due to well designed and easy-to-use interfaces, and in school curriculum Computer Science class was mostly filled with sessions on Excel Spreadsheets, Word-processing and other tools with a high abstraction level. The idea of Raspberry Pi was to provide those who wanted with an affordable, but capable platform for tinkering. Interestingly, this trend should coincide with the makers movement which have embraced DIY-electronics from the Arduino interface to 3D-printing.

What is the Raspberry Pi?

It’s a plain computer, very scaled down and very affordable. The A-model costs around 25 Pounds, and at 30 Pounds you get the B-model which comes with 512 MB RAM, two USB-sockets and an Ethernet adapter. Both versions have a SD-card reader (the SD card, not included in the price, functions as a hard-drive for the Pi), HDMI-port for visual (and sound) and 3.5 mm jack output for sound. Both devices is powered by a micro-USB plug, come with a 700 Mhz ARM processor (roadcom BCM2835 700MHz ARM1176JZFS processor with FPU and Videocore 4 GPU) and a dedicated graphics unit which supports OpenGL and 1080p30 H.264 video (which is great since a 700Mhz processor is not too found of running high-res video in adition to the OS). It also comes with an RCA composite video output and CPIO ports, the latter may have a good potential if you want the Raspberry Pi to work as a stand-alone Arduino-like device.

Perhaps the most imporant part about the Raspberry Pi is that it can be used for many things, and that it has a low-level entry cost. With the HDMI and RCA you could use it as a media center, or you could buy a SNES-controller adapter and use it as a Super Nintendo with the ZSNES emulator. This makes it a brilliant tinkering device.

After ordering a HDMI to DVI adapter I finally got my Raspberry up and running and I will be back with some projects built on this platform soon. Stay tuned!

Getting it up and running is just plug-and-play if you have a preloaded SD-card. If not it is a bit more hazzle, I used this introduction on how to Install the Operating system onto the SD-card and it worked well using the Mac OSX Terminal to load the Raspbian OS over on the card following the instructions.

[nggallery id=11]