Thursday, June 10, 2010

[OpenOffice] From database to bibtex entry

For those struggling in the conversion from OpenOffice Bibliography database to bibtex entry. I've generated a small ruby script that makes the translation. This is for open office 3.2.
If any of you knows a more robust tool (probably already embedded in OpenOffice, which I could not find), please let me know.

The process to do this would be:

  1. Find the database file (dbf) in your local directory (usually under the .openoffice.org/3/user/database/biblio/ directory)
  2. Open the file with OpenOffice Calc (or Excel) and export it to CSV (make sure you specify ";" as field delimiter)
  3. Run the following script, putting as first argument in the command file the CSV file that you created in the previous step.
Let me know if you have further questions.

Good luck!



#!/usr/bin/ruby
#-----------------------------------------------------------------------
#
# dbf_to_bibtex.rb
# Script to transform from OpenOffice dbf to bibtex compliant format
#
# Change Log
# 20100610 MGF Created
#
# @ Miquel Garcia-Fernandez
#
#-----------------------------------------------------------------------


# Retrieve the CSV filename to parse
file_name = ARGV[0]
file = File.open( file_name, "r" )

# Field identifiers
identifiers = Array.new

CATEGORY = { "0" => "article",
"1" => "book",
"8" => "techreport",
"16" => "misc", }

file.each_with_index do |line,i_line|

# Retrieve the field identifiers
if i_line==0 then
fields = line.split(";")

fields.each_with_index do |field,i_field|
# Clean from double quotes and remove characters after comma
identifier = field.delete("\"").split(",").flatten[0]
identifiers << identifier.downcase
end

# Go to next line
next
end

# Now parse each field and generate bibtex entry
fields = line.split(";")

# Hash holding the valid entries of the current reference
entries = Hash.new

fields.each_with_index do |field, i_field|
clean_field = field.delete("\"")

next if clean_field.size == 0

entries[ identifiers[i_field] ] = clean_field

end

# Generate bibtex entry for the current line
print "@#{CATEGORY[ entries["type"] ]}{#{entries["identifier"].gsub(/ .*, /,':').gsub(', ',':')},\n"
entries.each_pair do |key,value|
next if key=="type"
next if key=="identifier"
next if key=="isbn"

print " #{key} = \"#{value}\",\n"
end
print "}\n\n"

end



Thursday, March 11, 2010

Checking out revisions from a Subversion repo with SSH + cPanel

If you are using cPanel for a web hosting and require to have a subversion repository in order to develop your code and checking it out/commiting remotely, you will need to properly configure it using SSH protocol. This post briefly describes how to do it. The basis of this short tutorial is based on the A2 hosting wiki that you will be able to find in this link. Follow these steps:
  1. First thing you will have to do is to generate a public/private keys (this step has been detailed in a previous post on this blog, see here)
  2. Of course, generate, in the server, the subversion repository with svnadmin. I'll assume that the repository lies in the following path /home/username/svn and the URL of the subversion is www.example.com.
  3. Edit the client/local file ~/.subversion/config and under the [tunnels] section, add the following line (assuming that the SSH connections in your cPanel host service provided go through the port 2222)
    cpanel = ssh -p 2222
    By doing this you are creating a new protocol for subversion that uses SSH for the specified port

  4. In the client/local machine, you will be able to check out from the subversion repository entering the following command line:
    svn co svn+cpanel://username@example.com/home/username/svn
When doing this I've found some scary outputs ("stdin: is not a tty" and "Killed by signal 15.") but the code has been correctly checked out.

Saturday, February 27, 2010

[iPhone] Combining Nav Bar and Tab Bars

After watching the Lecture #7 of the iPhone Programming course from Stanford University (which you can found here), the implementation of navigation bars was quite clear to me. However I had a bit of difficulties to understand how to combine table bars and navigation bars. Luckily enough I found this screen cast from OReilly's Elisabeth Robson in Youtube:



In order to get the general process of building such an application I am writing here some conceptuals steps to follow when combining Tab bars and navigation bars. I hope it helps you as well.

  1. Make new iPhone project in XCode (Window based application)
  2. Create the rootController as a UITabBarController (not as a UINavigationController since the tab bar will be the main tool you will use to move through the application). This root controller will go into the Application delegate as an IBOutlet.
  3. The Tab bar will be the first view, therefore the view has to be added in the "applicationDidFinishLaunching" method.
  4. Open the Interface Builder for the Main Window and drag a Tab bar controller into the window so you can hook it up to the outlet you created in the AppDelegate.
  5. For the navigation bar, an associated controller has to be created (it must he a subclass of UINavigationController). Note that the navigation bar has its own view to which the different views will be stacked.
  6. Also an IBOutlet for the navigation controller must be created in the application delegate (don't forget to reference the class with the @class directive).
  7. This tutorial features a table besides the tab bar and navigation bar, therefore we need to create a controller for the table view (so we can manage the table view).
  8. In the Table view controller do not forget to create the outlet to the table view that the table view controller will manage.
  9. Create a new NIB for the table view and associate its File Owner to the table view controller.
  10. In this example, the table view controller is also the delegate and datasource of the Table and as such it will contain an array that will hold the data (the array is created in the viewDidLoad method of the Table view controller).
  11. Set the title of the Table View Controller. This title is the one that will appear in the Navigation bar. Note, the screen cast uses NSLocalizedString to set the title. This class is useful for generating strings that will have to change depending on the language.
  12. In the numberOfRowsInSection, we must set up the size of our array. Also set the content of the row at indexPath in the cellForRowAtIndexPath. Note that the screencast uses the cell.text field to set up the field. In iPhone OS 3.0 this is deprecated. You should use cell.textLabel.text property instead. So, in the tutorial, instead of using
    cell.text =  [bookArray objectAtIndex:row] ;
    use
    cell.textLabel.text = [bookArray objectAtIndex:row] ;

  13. We need to create a simple view that will display the details of each book. So proceed to create a UIViewController class with the associated NIB and do the corresponding class and view hooks.
  14. Then we must inform the TableViewController about this View (since the Table View controller will push and pop the detail view controller, it must have a reference).
  15. In the definition file of the TableViewController do not forget to import the detail view controller AND the Application Delegate since we will need to have access to the navigation bar controller (in order to push and pop views)
  16. The push of the detail view controller will be done in the didSelectRowAtIndexPath method. In this tutorial the navigation controller that pushes the view is done via calling the delegate of the AppDelegate and then accessing the navigation controller. Alternatively, from the Stanford tutorial, it seems that the TableViewController can access the navigation Controller using the following line.
    [self.navigationController pushViewController:bookDetailViewController animated:YES];

Let me know if you have comments on this post.

Enjoy!

Sunday, February 21, 2010

How to use XML Builder templates in Rails (I)

For an application I had to generate a customized XML view in a Rails application. As it is known, Rails comes with the Builder gem that is a tool to render XML files from templates. Documentation of this gem can be found in Rubyforge or in Ruby API description.

In order to customize this xml, I used as a starting point this stackoverflow post. For this purpose I have created a simple Rails application using scaffolding (employees) with a single database table that is a list of employees with the following 4 fields: age, category, family name and given name). In order to customize the XML when the user types http://localhost:3000/employees/1.xml (for instance), do the following:
  1. Create a builder template that is called, for instance, show.builder, this template is the one that will be used to show the database entry (in my sample application it would be (http://0.0.0.0:3000/employees/1.xml). The code of this template is the following (tags are in spanish):

    xml.instruct!

    xml.employee do

    xml.nombre(@employee.given_name)
    xml.apellido(@employee.family_name)
    xml.edad(@employee.age)
    xml.categoria(@employee.category)

    end

  2. In the controller (in my case employee_controller) I had to substitute the line

    format.xml { render :xml => @employee }

    by the line

    format.xml { @employee }

    Otherwise the application will render the XML in the default mode. If you still want to keep the default XML format, you can always redirect the rendering using the routes.cb configuration file.
If in addition you want to generate the XML and send to the user (besides showing it in the browser, change the previous format line:

format.xml { @employee }

by

format.xml do
stream = render_to_string(:template=>"employees/show.builder" )
send_data(stream, :type=>"text/xml",:filename => "test.xml")
end


This way, the Rails application renders the template and places it in stream and afterwards send this data into the test.xml file.

That's it!

Tuesday, January 12, 2010

Fast SSH login (without passwords)

This simple tutorial has been extracted from "Peters's Blog". To avoid retype of password in ssh remote connections, follow the next steps:

  1. install openssh on client and server
  2. create ssh key using:
    ssh-keygen -t dsa
  3. Log into server using sftp
  4. copy the file id_dsa.pub (generated in the client) to the server
  5. on the server, merge contents of (client) id_dsa.pub with ~/.ssh/authorized_keys2
  6. From client, try logging in using ssh or sftp. Key should be accepted.

Thursday, May 21, 2009

Example of vimrc

Let's face it,IDEs are fancy and cool, but I sometimes wonder to what extent these tools distract us with the real thing: programming. In this sense, the austerity of vi or vim may be helpful to really focus on the programming tasks. Besides, the fact that is console based makes us aware of the file structure of the application we are developing. I like NetBeans a lot, but frankly speaking, I get a bit lost on the file directory when developing Ruby on Rails applications. I really recommend vim even for this purpose. The learning curve may be daunting at first. But I think that it pays at the end (and not only for RoR, but also for Matlab and IDL programs).

Here I post a small snippet with the vimrc I am using.


" Syntax highlighting
syntax on

" Use spaces instead of tabs
set expandtab

" Set numbering
set numberwidth=5
set number

" Set autoindentation with 4 space indentation
set autoindent
set shiftwidth=4

" Set the ruler
set ruler

" Set the CUDA filetype
au BufNewFile,BufRead *.cu set ft=cu
"au BufNewFile,BufRead *.gnu set ft=gnuplot

" Set the searc highlight
set hlsearch

" Set syntax automatic folding
set foldmethod=syntax

" Set foldcolumns
set foldcolumn=3

" Set colorscheme to desert
colorscheme desert

" Instructions to print
" Courtesy of http://vim.wikia.com/wiki/Print_to_a_Postscript_file
let &printexpr="(v:cmdarg=='' ? ".
\"system('lpr' . (&printdevice == '' ? '' : ' -P' . &printdevice)".
\". ' ' . v:fname_in) . delete(v:fname_in) + v:shell_error".
\" : system('mv '.v:fname_in.' '.v:cmdarg) + v:shell_error)"


Wednesday, May 20, 2009

Popular Places

The following ruby program is the one used to compute the most popular places in the world based on the number of photos for a given cell. The program generates the grid (based on latitude and longitude ranges and resolutions), queries panoramio and parses the result looking for the keyword "count". The results can be seen at my blog at Starlab.

The use of this program is the following: At the command line type:


PoPlaces minLong maxLong minLat maxLat longResolution latResolution



Note: The values have to be given in degrees.


#!/usr/bin/ruby
#-------------------------------------------------------------------------------
#
# PoPlaces.rb
#
# The purpose of this Ruby program is to retrieve the number of photographs
# for a set of cells defined by the user defined area (with a certain longitude
# and latitude resolution
#
# References:
# - Panoramio API : http://www.panoramio.com/api
#
#
# @ Miquel Garcia Fernandez, May 2009
#
# Contact me at: miquel.garciafernandez@gmail.com
#
#-------------------------------------------------------------------------------

# HTTP library is required
require 'net/http'

# Create default values for Longitude, latitude and resolution
dLongMin = -180.0
dLongMax = +180.0

dLatMin = -90.0
dLatMax = +90.0

dLongRes = 0.5
dLatRes = 0.25

# Parse the argument list if any
ARGV.each_with_index do |a, i_a|
dLongMin = a.to_f if i_a == 0
dLongMax = a.to_f if i_a == 1

dLatMin = a.to_f if i_a == 2
dLatMax = a.to_f if i_a == 3

dLongRes = a.to_f if i_a == 4
dLatRes = a.to_f if i_a == 5
end

# Compute the number of cells required in longitude and latitude
iNLongs = (dLongMax - dLongMin)/dLongRes ;
iNLats = (dLatMax - dLatMin)/dLatRes ;

# Loop over all latitudinal and longitudinal indices
(0...iNLongs).each do |iLong|

(0...iNLats).each do |iLat|

# Define the central point of the cell
dLong = dLongMin + dLongRes*(iLong + 1.0/2.0)
dLat = dLatMin + dLatRes*(iLat + 1.0/2.0)

# Define the vertices of the cell
dLongIntMax = dLong + dLongRes/2.0
dLongIntMin = dLong - dLongRes/2.0
dLatIntMax = dLat + dLatRes/2.0
dLatIntMin = dLat - dLatRes/2.0

# Retrieve the number of photos in Panoramio
url = "www.panoramio.com"
uri = "/map/get_panoramas.php?order=popularity&set=public&from=0&to=1&" +
"minx=#{dLongIntMin}&miny=#{dLatIntMin}&" +
"maxx=#{dLongIntMax}&maxy=#{dLatIntMax}&size=medium"
res = Net::HTTP.get(url, uri)

# Parse the Panoramio output in order to extract the photo count for the
# current cell
iNPhotos = 0
res.each \
{ |line| iNPhotos= /[0-9]+/.match(line)[0] if line=~/\{ \"count\":/ }

# Output the result to the standard output
print "%7.2f %7.2f %7.2f %7.2f %7d\n" %
[dLongIntMin, dLongIntMax, dLatIntMin, dLatIntMax, iNPhotos]

end # End of inner loop (latitudes)

end # End of outer loop (longitudes)