Saturday, April 26, 2008

RXTX and the funky PortInUseException on Macosx

I am using the RXTX serial libs for getting data out of my gps. They always worked nice, but the first time I tried them on Macosx they didn't work, throwing this ugly:

gnu.io.PortInUseException: Unknown Application

Since the thing worked from commandline:
>>> cat /dev/tty.touchGPS-SSP-1
$GPGGA,172025.233,2500.0001,N,12159.9999,E,0,0,,80.9,M,16.1,M,,*7D
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGSV,1,1,00*79
$GPRMC,172025.233,V,2500.0001,N,12159.9999,E,0.00,0.00,260408,,,N*77
$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32... etc etc

I was pretty helpless. Then I found in some mailinglist archive the solution. To cite the guy that solved my problem: "As I've discovered the PortInUseException rarely has anything to do the port being in use. For reasons I don't understand RXTX is not using /var/spool/uucp for lock files. It's using /var/lock. A directory that didn't exist on my system. Once I created this directory I started getting different errors for the RXTX code. This directory requires read/write permissions for the user. I just used the blanket chmod 777."


Nothing to add, tried it and it worked.






UPDATE as of Saturday 4th of April 2009:


As a nice anonymous user comments, these are the steps to go:
  1. Open 'Terminal' from Applications->Utilities
  2. Enter the commands:
sudo mkdir /var/lock   (hit enter end type your password)
sudo chmod 777 /var/lock (hit enter again)

Friday, April 25, 2008

Free Software Evangelists and the ultimate truth

I am following this thread in the osgeo list: Can I do the same GIS tasks with OS (as with ESRI)?

Paul Ramsey states and I would not find better words:
"I think it's contingent on us as evangelizers to not over-sell. I would not recommend QGIS or any other open source desktop to someone whose prior experience was Arc* until I had a clear understanding of the use case."

The truth is that too often we tend to oversell (I guess because we have too much passion for what we do), giving people the right reason to complain about open source software.

Thursday, April 24, 2008

What is going on with case sensitivity on *nix systems?

I think I'm going mad (due to my ignorance, since I guess this is known...)!!

On my macosx I made I typo in trying to enter a folder (note that USers doesn't exist):

[10:04 - Thu_24_Apr_2008 by moovida on moovida-2 ][1 ~]
>>> cd /USers/moovida//codeapisexes/imageiobuild/gdalbuild/gdal1.4.4/data/

But hey, I could enter:

[10:04 - Thu_24_Apr_2008 by moovida on moovida-2 ][2 /USers/moovida/codeapisexes/imageiobuild/gdalbuild/gdal1.4.4/data]
>>> pwd
/USers/moovida/codeapisexes/imageiobuild/gdalbuild/gdal1.4.4/data

So to be sure I didn't do anything nasty in the past, as for example renaming my home folder (which is impossible) or relink it.. or ... or aliens came to take me:

[10:04 - Thu_24_Apr_2008 by moovida on moovida-2 ][3 /USers/moovida/codeapisexes/imageiobuild/gdalbuild/gdal1.4.4/data]
>>> ll /
total 41029
drwxrwxr-x+ 116 root admin 3.9K Apr 19 10:17 Applications
-rw-r--r--@ 1 root admin 1.0K Nov 18 22:58 Desktop DB
-rw-r--r--@ 1 root admin 2B Nov 15 20:04 Desktop DF
drwxrwxr-x@ 16 root admin 544B Nov 27 00:43 Developer
drwxrwxr-t+ 57 root admin 1.9K Jan 20 23:01 Library
drwxr-xr-x@ 2 root wheel 68B Sep 23 2007 Network
drwxr-xr-x 4 root wheel 136B Feb 13 17:30 System
drwxrwxrwx@ 3 root wheel 102B Dec 13 22:45 TheVolumeSettingsFolder
lrwxr-xr-x 1 root admin 60B Nov 15 15:56 User Guides And Information -> /Library/Documentation/User Guides and Information.localized
drwxr-xr-x 5 root admin 170B Nov 15 15:55 Users

Ha ha, Users is != USers...

[10:04 - Thu_24_Apr_2008 by moovida on moovida-2 ][4 /USers/moovida/codeapisexes/imageiobuild/gdalbuild/gdal1.4.4/data]
>>> cd /Users/moovida//codeapisexes/imageiobuild/gdalbuild/gdal1.4.4/data/

Works also... so is the filesystem case sensitive or not?

Wednesday, April 23, 2008

Groovy, groovy, groovy, groovy... (like Kaiser Chiefs)

Since some discussion has been done around groovy in the udig list lately, and since I traveled a lot by train lately, I found the time to dive into the Groovy language.

My God, did I like what I read!!
I will probably never script again in bash, whenever I am allowed to choose!!

And the fact that java and groovy can coexist!! And pointers on methods!! And... and... and...
Well, I wrote down some starter code for those that do not know groovy. Just to have a look.

So start the groovy, groovy, groovy, groovy song...



...and enjoy!!!


/*
* STRINGS MAGIC
*/
/*
* in groovy you don't have to define the type
*/
def string = "test string" // you don't need to put a semicolon at the end
println string
// want to quote a word? singlequote the whole and just do it
string = 'test "string"'
println string
// the resulting class is a java string
println string.class
println ""
println "*****************************************************"
println ""

/*
* heredocs, a great way to hold everything inside a string,
* without to care about quoting and xml slashes or brackets
*/
def xmlString = """inside here you can write whatever you want,
you can also embed xml with al its nasty characters:

can you imagine to do this in java?

"""
println xmlString
// and it is a java string!
println xmlString.class
println ""
println "*****************************************************"
println ""

/*
* so let's go one step further, introducing GStrings and using
* them together with heredocs to have fun
*/
def what = "whatever";
def question = "can you imagine to do this in java?";
def xmlGString = """inside here you can write ${what} you want,
you can also embed xml with al its nasty characters:

${question}

"""
println xmlGString;
// as you can see this time we have a groovy string implementation
println xmlGString.class;
println ""
println "*****************************************************"
println ""

/*
* LISTS MAGIC
*/
// define a list
def list = ["Merano","Bolzano","Trento"];
println list;
// defaults to ArrayList
println list.class;
// wanna cast? be dirty!
def listStringArray = ["Merano","Bolzano","Trento"] as String[];
println listStringArray;
println listStringArray.class;
def listSet = ["Merano","Bolzano","Trento"] as Set;
println listSet;
println listSet.class;
// add an element
list << "Lagundo"
println list;
println list.class;
// btw you can treat lists and arrays the same way!!
println list.get(0) + " is the same as " + list[0];
// find elements
println list.findAll{it.endsWith("ano")}
println ""
println "*****************************************************"
println ""

/*
* LOOPS MAGIC
*/
// forget about for loops, use closures
// with default variable 'it'...
list.each{println it}
// ...or with your variable...
list.each{myVar ->
println myVar
}
// ...or with an index and your variable
list.eachWithIndex{myVar, i ->
println "${i}: ${myVar}"
}
// sort...
list.sort();
println list
// and reverse sort
def revList = list.reverse();
// but note that while sort changes the original list,
// reverse makes a copy
println list
println revList
// concatenate list
def abc = ["a","b","c"]
def cde = ["c","d","e"]
def newabcde = abc + cde
println newabcde
// join the list to one single string
println newabcde.join(",")
println newabcde.join(" | ")
// max min and so on?
println abc.max()
println abc.min()
println abc.sum()
// modify each element of the list with collect
def newCollectedAbcde = newabcde.collect{
it += " is a letter"
}
newCollectedAbcde.each{println it}
// flatten nested lists
def newNestedList = ["a", "b", "c"]
newNestedList << cde
println newNestedList
println newNestedList.flatten()
// the spread-dot operator, execute mthods on every element
// this would not work: println abc.toUpperCase()
// whereas this will:
println abc*.toUpperCase()
println ""
println "*****************************************************"
println ""

/*
* MAPS MAGIC
*/
def townsProvinceMap = [merano:"BZ", bolzano:"BZ", trento:"TN"]
println townsProvinceMap
// defaults to linked hashmap
println townsProvinceMap.getClass()
// why I didn't use .class instead of getClass? Because of the way
// of getting values from the map:
println townsProvinceMap.merano
// therefor the following will give null
println townsProvinceMap.class
// add an element
townsProvinceMap.lagundo = "BZ"
println townsProvinceMap
// iterate the thing with the default value...
townsProvinceMap.each{println it}
// ...or with key and value separated...
townsProvinceMap.each{println "${it.key} is in province of ${it.value}"}
// ...or with own vars
townsProvinceMap.each{k, v ->
println "${k} is in province of ${v}"
}
println ""
println "*****************************************************"
println ""

/*
* RANGES MAGIC
*/
def range = 1..3
println range.class
// do some iterations
range.each{println it}
range.each{println "what?"}
// and what about dates?
def now = new Date();
def nextWeek = now + 7;
(now..nextWeek).each{
println it
}
// since ranges have a from, to and size...
println range.from
println range.to
println range.size()
// ...you can use them in for loops...
for (i in 1..3){ println "step number: ${i}"}
// ...which ovbiously could be done like the following
(1..3).each{ println "closure step number: ${it}"}
println ""
println "*****************************************************"
println ""

/*
* COMMAND LINE ARGUMENTS?
*/
if(args){
// this if checks both if args is != null and also not empty
println "supplied commandline args:"
args.each{println it}

} else {
println """
The commandline arguments part was not executed, since no argument was supplied.
"""
}
println ""
println "*****************************************************"
println ""

/*
* SYSTEM ENVIRONMENT
*/
System.env.each{ println it}
def userHome = System.getenv("HOME")
println userHome
println ""
println "*****************************************************"
println ""

/*
* FILES MAGIC
*/
// list a folder's content
def upperFolder = new File("..")
println "The contents of " + upperFolder.absolutePath + " are:"
upperFolder.eachFile{ file ->
println file
}
println "...of which folders:"
upperFolder.eachDir{ dir ->
println dir
}
println "...of which files:"
upperFolder.eachFile{ file ->
if(file.isFile())
println file
}
// recursive list content
println "Recursive folders content:"
upperFolder.eachDirRecurse{ dir ->
println dir
}
println ""
println "*****************************************************"
println ""

// read and write a file
// start with creating a new file to be read afterwards
def filePath = "./testFileToBeRemoved.txt"
def newFile = new File(filePath);
newFile.write("""A new header.
A new testline.
A second testline.
""")

// read the file and print the content
new File(filePath).eachLine{ println it }
// read the file into a string variable
def content = new File(filePath).text
println content
// append some content
def file = new File(filePath);
file << "Some text after the last line is appended!"
println file.text
// merge files
def file2 = new File(filePath + "2")
file2.write("Content of file 2");
println file2.text
def mergedFile = new File(filePath + "_merged")
mergedFile << file.text
mergedFile << file2.text
println "\nThe merged file:"
println mergedFile.text



And note that the above works as a compiled class as well as a command-line script!!

Sunday, April 20, 2008

Back from EGU, history repeats, the new bel paese

Back from EGU, back from Vienna... Berlusconi is back... but we knew it all before, as stated already back in the 1995 in the The Globalization Trap: The 20-80 Society, by H.P. Martin and H. Schuhmann:


The pragmatists in the Fairmont Hotel reduce the future to a pair of numbers and a term: "20 to 80" and "tittytainment".

20 percent of the working age population will be enough in the coming century to keep the world economy going. "More workers will not be needed", said magnate Washington SyCip. A fifth of all jobseekers will be enough to produce all the goods and perform all the top-flight services that the world society can afford. This 20 percent will actively participate in living, earning and consuming. One or two percent may be added, the discussants admit, perhaps wealthy heirs.


What about the others? Will 80 percent of those willing to work be without a job? "Certainly", says the US author Jeremy Rifkin, author of the book "The End of Work". "80 percent will have enormous problems." Sun manager Gage puts some more coal on the fire and appeals to his boss Scott McNealy: The question in the future will be "to have lunch or be lunch", to eat or be devoured.

[...]
The term "tittytainment" makes the rounds. This term was coined by the old war-horse Zbigniew Brzezinski. The native Pole, National Security advisor of US president Jimmy Carter, has been occupied with geo-strategic questions. "Tittytainment", Brzezinski explains, is a combination of "entertainment" and "tits", the American slang for bosoms. Brzezinski thinks more of the milk streaming from the breast of a nursing mother than of sex. The frustrated population of the world could be kept happy with as mixture of numbing entertainment and adequate food.

- excerpt from a translation found here http://portland.indymedia.org/en/2004/02/280805.shtml

For the following, strictly Italy-related, I could not find a proper translation:

[...]
Persino nel bel paese, dove la fantasia latina sembra riuscire ad escogitare sempre nuove vie per evitare un tacollo che appare non di rado imminente, e' arrivata l'onda xenofoba e insieme ad essa si diffondono, nelle province settentrionali, l'ira contro il governo centrale, nonche' la voglia di staccarsi dal meridione che "mangia pane a tradimento". Agli occhi dei nordisti di Bossi il sud, la "Terronia", si presenta come una sorta di appendice settentrionale dell'Africa e fa parte del terzo e quarto mondo, mentre la loro "Padania" sarebbe efficiente, produttiva, moderna, onesta. Dove l'economia non funziona, gli Italiani sono invitati ad affidare il loro futuro a ogni sorta di "gratta e vinci", sfornati di continuo dal governo italiano (anche quello democratico dell'Ulivo) per dare un qualche scopo alla vita di milioni di persone. Per il resto l'Italia bada a realizzare il suo tittytainment, i suoi "panem et circenses". Basti pensare alla tv di Berlusconi (e non solo), alle canzonette nazionalpopolari di Sanremo, alle imprese di Tomba e alla nazionale di calcio.

[...]
In Italia a Silvio Berlusconi e' riuscito persino un colpo che in qualsiasi altro paese sarebbe ancor oggi inimmaginabile. Dalle sue tv tutto spot e consumismo e dalle sue squadre sportive con il Milan in testa - vero oppio del popolo italiano - e' riuscito a portare i sogni dalle sue televisioni sin dentro i palazzi del potere politico, arrivare a fondare un partito e a farsi eleggere presidente del consiglio dei ministri.


So were the hell did we learn from our history?!?

And you, are you 20 or 80? And more over, what will your kids get? And their kids? Ah, right, you do not care...

Thursday, April 10, 2008

How to create a command OR Presenting the actions-commands-console-openmi-uibuilder taskforce

You want to implement a new model/algorithm/command/action/do-something (MACAD) in JGrass?

Here more or less the full list of things to do. More or less is due to the fact that I assume you already know the JGrass or at least the Udig or at very least the Eclipse RCP development environment. Also some sort of OpenMI knowledge should be here. All in all I'm not sure how many will find this useful. Hmmm... I'm sure at least one of the chapters could be.
Why I'm doing this? Because next week I have to present a whole bunch of the JGrass stuff at the EGU and I need some docu. Enjoy :)


UPDATE: please note that now the steps 1 and 2 are done the clean rcp way throught extension points. Read here for more info.

1) Create your MACAD

My example will treat an OpenMI based model, i.e. h.pitfiller.

The model extends ModelsBackbone, which implements OpenMI's interface ILinkableComponent.

Create such a MACAD and implement the needed methods.

2) Tell the console engine that the new model is there

In the list of available MACADs add your new model, so that the engine knows that your MACAD exists.
The line looks like the selected in the image below:



which basically tells us what the model's name and class are.
Also information is given about the arms the MACAD has. In this case 2 arm, which define the input elevation map and the output depitted map.

Note that at this point the model h.pitfiller can already be used in the JGrass console as
h.pitfiller --igrass-elevation elevation --ograss-pit pit



3) create a gui xml file definition for the MACAD (the UIBuilder of JGrass)

Create a file with the same name of the MACAD and xml extention and fill it with the following:





The first line will create a label of text descr, a textfield and a button that opens a map selection window.
The second creates a label of text descr and a textfield for the output map name.

When ok is pressed, the widget creates a command string build by the name of the command tag and the repr of the fileds tags, substituting the # with the user input:
h.pitfiller --igrass-elevation userinput --ograss-pit userinput


4) create an rcp action to launch the command

Once the gui definition is there, we need something to trigger the action.

Eclipse RCP's actionset comes to help us. I create a plugin inside which I keep all the gui for console commands and create an action. In the below image you can see the whole context with adifferent menus and action groups.


Please note the textfield class, inside which I put: eu.hydrologis.jgrass.ui.actions.h_pitfiller

The class MUST have the same name as the MACAD you want to create!
Let's create the class by clicking over the hyperlinked text class which will create the action class with all the needed implementation of interfaces and methods.


And now the same class with the needed changes:



Apply the same changes and that is all. If you didn't do so, put the xml gui definition file inside the same package as the action class. Take a look at the screenshot above to see how it should look inside of the actions package.

5) try it out!

Launch JGrass and search in the menu bar your new item. In my case there are a lot, as I already have a whole bunch of organised MACADs in my configuration. However, here I go with pitfiller:



and the autogenerated gui looks like:


6) what happens when I click ok?

The uibuilder creates the commandline representation of the command line execution.
After that the command is passed to the console engine and a backtrace console window is attached to the process in order to deal with output and errormessages.

So the running h.pitfiller command looks like the following:






The same could have been done with any GRASS command, apart of the fact that you will not need to create the MACAD yourself :)

Alright, so let's see how to do the same with r.in.gdal, the GRASS native high power raster data import tool.

What you have to do different from before, is that when you create the action class, you need to tell the execution facility class that it is a GRASS command:


Create the xml file with the options you need:



and fully enjoy your new command:


Tuesday, April 8, 2008