20091231
Order Matters With XCode's Build Phrases
I use a custom script to insert the current git commit into GeoNote, so when I get bug reports I have a better idea of which version the user is running. The script is as below:
import os
from Foundation import NSMutableDictionary
version = os.popen4("/sw/bin/git rev-parse --short HEAD")[1].read()
info = os.environ['INFOPLIST_FILE']
print info
plist = NSMutableDictionary.dictionaryWithContentsOfFile_(info)
print plist
plist['revision'] = version[:-1]
plist.writeToFile_atomically_(info, 1)
This was added as a Run Script Build Phrase. The problem I noticed was that the commit short hash inserted into Info.plist was always one commit behind. After some head scratching, I realised this was because by default the new build phrase is inserted last, and the order matters! It isn't actually possible to reorder build phrases by drag and dropping the children nodes around. You have to do a head-insert by dragging a child to the parent, which inserts it at the top.
Voila, problem solved.
Cheers,Steve
20091216
Yet Another Arduino Float Print Function
void floatPrint(float f, int places=6)
{
int _d;
if (f < 0)
{
Serial.print("-");
f*=-1;
}
_d = (int)f;
if (!places)
{
return;
}
Serial.print(_d, DEC);
Serial.print('.');
while(places--)
{
f-=_d;
f*=10;
_d = (int)f;
Serial.print(_d, DEC);
}
}
void floatPrintln(double f, int places=6)
{
floatPrint(f, places);
Serial.println();
}
Why another float print function? The ones I found wasn't too nice, one of which required long integers. Yuck. It was also fun, and now I know where to look for one in the future :P
Cheers,
Steve
20091207
A subtle source of linker errors under XCode
If one source file is sourcecode.c.objc and another is sourcecode.cpp.objcpp, you will have problems if you try to call function defined in one file from the other. The resolve this either make them the same source type, or follow this guide.
This drove me nutty because the template I was working off has code set to sourcecode.cpp.objcpp, but XCode adds new classes as sourcecode.c.objc! To check the file type, use "Get Info" in the source file's context menu.
Cheers,
Steve
20091011
qrbackup
I generated a gpg keypair for myself today, and I was looking for a fairly safe way to back it up. I don't particularly trust DVD/CDs, and keeping it on flash is even more worrying. I wanted a means of backup I can see and touch.
Paperbak would be great if it was ported to something not windows. Since it wasn't, I settled on QR Code.
Thus qrbackup was born. It will base32 encode a file, then encode it into QR codes using google chart service.
I have tested it from backup to restoration, and it works. YMMV, more instructions available after the jump.
Cheers,
Steve
P.S. Pardon my python.
Labels: code, python, software
20090805
git-daemon on debian vserver
Annoyingly git-daemon-run requires runit on debian, but runit will fail to install properly in a debian vserver because it doesn't have init.
One solution is to reconfigure vserver to use plain init style.
However I didn't want to this because I don't want to take down my vserver just yet. So here is the required line for /etc/inetd.conf:
git stream tcp nowait nobody /usr/bin/git git daemon --inetd /var/git-repos
Cheers,
Steve
20090607
Dealing with rkhunter warnings
rkhunter often warns on file property changes after upgrade and such, and sometimes you just aren't sure whether it is due to recent upgrades, or because you really were compromised. The following script was written to compare the checksum of all files rkhunter warns about against the originals in a debian repository.
The latest version of this is available in my script.git respos.
#!/bin/bash
desc="
This script will verify whether files for which rkhunter has logged a
warning for is still valid. It does this by finding which debian package
it came out of, and downloads them, unpacks them, then checks
the checksums.
Run it by supplying a rkhunter log file as first argument
"
HASHER="sha256sum"
IFS="
"
function find_suspect_files
{
echo "parsing $1 for suspect files" 1>&2
grep -1 Warning "$1"| grep File | sed 's|.*File: ||'
}
function find_packages
{
echo "finding packages" 1>&2
for suspect_file in $1
do
package=$(dpkg -S $suspect_file|awk '{print $1}'|sed 's/.$//')
echo "suspect file $suspect_file found in $package" 1>&2
echo $package
done
}
function make_aptitude_args
{
echo "generating aptitude arguments" 1>&2
for package in $1
do
version=$(dpkg -p $package | grep Version | awk '{print $2}')
echo $package=$version
done
}
function cleanup
{
echo "cleaning up"
popd
rm -rf tmp
exit $1
}
function setup
{
echo "setting up"
rm -rf tmp
mkdir tmp
pushd tmp
}
if [ $# -ne 1 ];
then
echo "$desc"
exit 1
fi
suspect_files=$(find_suspect_files "$1")
packages=$(find_packages "$suspect_files" | sort | uniq)
if [ -z "$packages" ];
then
echo "***WARNING****"
echo "No packages contain any of the suspect files!"
cleanup 1
fi
aptitude_args=$(make_aptitude_args "$packages")
setup
echo "downloading packages"
aptitude download $aptitude_args 1>/dev/null
if [ $? -ne 0 ];
then
echo "aptitude download failed!"
echo "args=$aptitude_args"
cleanup 1
fi
echo "unpacking"
for deb_file in *.deb
do
ar -x $deb_file
tar zxf data.tar.gz
rm -rf data.tar.gz control.tar.gz
done
for suspect_file in $suspect_files
do
if [ ! -f ".$suspect_file" ]
then
echo "***WARNING****"
echo "For some reason .$suspect_file does not exis!"
continue
fi
echo -n "verifying $suspect_file... "
suspect_sum=$($HASHER $suspect_file | awk '{print $1}')
clean_sum=$($HASHER ".$suspect_file" | awk '{print $1}')
if [ $suspect_sum == $clean_sum ];
then
echo "OK"
else
echo
echo "***WARNING****"
echo "Checksum mistmatch for $suspect_file!!!"
echo "Should be: $clean_sum"
echo "Is: $suspect_sum"
fi
done
cleanup
Cheers,
Steve
20090518
Sketch to calibrate SEN-08663
Got my hands on a ADJD-S371 on a breakout board from Sparkfun. The code below can be used to calibrate it. The most up-to-date version of the code can be found at my git repository under colour_sensor_calibration.
#include <Wire.h>
/* Calibrates the sensor to get white balance. Pin 2 should be connected
* to LED on the breakout board's LED pin. Calibration is done by placing the
* breakout board inside a pin pong ball, and using the built-in LED for
* illumination.
*
* Amount of light is measured by charging N capacitors for time X then
* reading off the voltage. (Conjecture)
*
* N is controlled by CAP_XXX
* T is controlled by INT_XXX
*
* Calibration is done by adjusting the integration time. No real reason.
*/
int _slave_id = 0x74;
int _LED_pin = 2;
uint8_t read_register(uint8_t addr)
{
i2c_send(_slave_id, &addr, 1);
return i2c_read(_slave_id);
}
void write_register_int(uint8_t addr, int data)
{
write_register_multibyte(addr, (uint8_t*)&data, 2);
}
/* write data[i] = register+i */
void write_register_multibyte(uint8_t addr, uint8_t* data, uint8_t bytes)
{
for (int i = 0; i < bytes; ++i)
{
write_register(addr+i, data[i]);
}
}
void write_register(uint8_t addr, uint8_t data)
{
uint8_t bytes[] = {addr, data};
i2c_send(_slave_id, bytes, 2);
}
uint8_t i2c_read(uint8_t id)
{
Wire.requestFrom(_slave_id, 1);
for(int i = 0; i<10 && !Wire.available(); ++i, delay(10));
if (!Wire.available())
{
return 11;
}
return Wire.receive();
}
void i2c_send(uint8_t id, uint8_t * data, uint8_t len)
{
Wire.beginTransmission(id);
for(int i = 0; i < len; ++i)
{
Wire.send(data[i]);
}
Wire.endTransmission();
}
#define CTRL 0x00
#define CONFIG 0x01
#define CAP_RED 0x06
#define CAP_GREEN 0x07
#define CAP_BLUE 0x08
#define INT_RED_LO 0x0A
#define INT_RED_HI 0x0B
#define INT_GREEN_LO 0x0C
#define INT_GREEN_HI 0x0D
#define INT_BLUE_LO 0x0E
#define INT_BLUE_HI 0x0F
#define DATA_RED_LO 0x40
#define DATA_RED_HI 0x41
#define DATA_GREEN_LO 0x42
#define DATA_GREEN_HI 0x43
#define DATA_BLUE_LO 0x44
#define DATA_BLUE_HI 0x45
int read_colour(uint8_t low_addr)
{
int lo = read_register(low_addr);
int hi = read_register(low_addr+1);
return lo|(hi<<8);
}
int red_integration_time = 2048;
int green_integration_time = 2048;
int blue_integration_time = 2048;
void set_integration_times(int red, int green, int blue)
{
write_register_int(INT_RED_LO, red);
write_register_int(INT_GREEN_LO, green);
write_register_int(INT_BLUE_LO, blue);
}
void setup()
{
pinMode(_LED_pin, OUTPUT);
digitalWrite(_LED_pin, HIGH);
Serial.begin(57600);
Wire.begin(); // join i2c bus (address optional for master)
Serial.println("Setting up...");
// datasheet says, wait 10us for hardware reset, so lets wait 1000
delay(1);
// gain setup
write_register(CAP_RED, 0x08);
write_register(CAP_GREEN, 0x08);
write_register(CAP_BLUE, 0x08);
set_integration_times(
red_integration_time,
green_integration_time,
blue_integration_time
);
// ask for colour data and offset
write_register(CTRL, 0x01);
}
void loop()
{
if (read_register(CTRL))
{
return;
}
int red, green, blue;
red = read_colour(DATA_RED_LO);
green = read_colour(DATA_GREEN_LO);
blue = read_colour(DATA_BLUE_LO);
Serial.println("--------------");
Serial.print("red: ");Serial.println(red);
Serial.print("green: ");Serial.println(green);
Serial.print("blue: ");Serial.println(blue);
Serial.print("red_int: ");Serial.println(red_integration_time);
Serial.print("green_int: ");Serial.println(green_integration_time);
Serial.print("blue_int: ");Serial.println(blue_integration_time);
// have to calibrate against blue, because LED has a blue bias otherwise
// it would look like blue has high gain than it does
float P = 1;
int reference = blue;
red_integration_time += (reference - red)*P;
green_integration_time += (reference - green)*P;
blue_integration_time += (reference - blue)*P;
// set the new integration times
set_integration_times(
red_integration_time,
green_integration_time,
blue_integration_time
);
// ask for colour data again
write_register(CTRL, 0x01);
}
Cheers,
Steve
Labels: arduino, code, electronics
20090508
Facebook python authentication gateway
Edit: it occurred to me what I have below is the basics of a thin facebook api wrapper. I might make it into one at some point in the future.
If you don't know what this does, you don't need it. Hope this helps some one. Written because pyfacebook is broken, always returns error 100.
FB_API_HOST="api.facebook.com"
FB_API_PATH="/restserver.php"
def get_session(auth_token):
params={
"api_key":FB_API_KEY,
"v":"1.0",
"auth_token":auth_token,
"generate_session_secret":1,
"method":"auth.getSession",
}
sorted = params.items()
sorted.sort(key=lambda x:x[0])
str_to_hash = ''.join(["%s=%s"%(x[0], x[1]) for x in sorted])
str_to_hash += FB_API_SECRET
md5 = hashlib.md5()
md5.update(str_to_hash)
sig = md5.hexdigest()
params["sig"] = sig
encoded_params = urllib.urlencode(params)
headers = {
"Content-type":"application/x-www-form-urlencoded",
}
conn = httplib.HTTPConnection(FB_API_HOST)
conn.request("POST", FB_API_PATH, encoded_params, headers)
response = conn.getresponse()
print response.status, response.reason
return response.read()
This Works For Me when I use it with iphone facebook-connect client:
[FBSession sessionForApplication:myApiKey getSessionProxy:myURL delegate:self];
Cheers,
Steve
Labels: code, internet, software
20090429
Stripping trailing whitespace from XCode
Firstly, my usual approach of s/\s+$//g doesn't work since it eats up the newline too. s/\s+$/\n/g doesn't work either because the Replace: field in the find dialogue doesn't escape the \n.
Final solution is as shown: s/[ \t]+$//g
Cheers,
Steve
Labels: code, computer, howto, osx, software
20090216
Arduino ultrasound ranger
Code to drive it is avaliable under GPL.
An updated version of the schematic as a .sch file is available also.
Cheers,
Steve
Labels: arduino, code, electronics, seeeduino
20090125
Auto leveller
A simple 2 DoF setup with an accelerometer (LIS302DL) attached to the effector. The seeeduino attempts to drive the servos so the Z and Y axis measure zero acceleration. The sketch is available at the usual place.
The algorithm employed is a simple PD controller with pseduo-gradient stepping to determine how to control each servo without any knowledge of how the servos are arranged. To deal with sensor noise from the accelerometer, a schmitt trigger mechanism is employed along with a moving average.
The code also allows the system to be calibrated to deal with accelerometer miscalibration.
It is cute, but that is about it :-) Coupled with a tripod and better construction ut might be useful for some DIY surveying or construction work.
Cheers,
Steve
Labels: arduino, code, electronics, seeeduino
20081226
DIY digital spirit level
A simply digital spirit level using a LIS302DL accelerometer from nkcelectronics coupled with a seeeduino for processing and a 2x16 character LCD display for output.
Sketch is available for your convenience. Note the Sketch includes an extra feature: PWM backlight on pin3.
Cheers,
Steve
Labels: code, electronics, seeeduino, software
20081009
Some people are going to hate me for this
But you can get the current function's name by using:
sys._getframe().f_code.co_name
Seems to work alright for debugging purposes. See the link embedded in the title for the origins and 3 other methods.
Cheers,
Steve
Labels: code, computer, python
20080716
unoffical libfg repository
I have set up an unofficial git respository for libfg patches and new swig generated python interface, as Gavin Baker (the author) appears to be busy with other things. This is a maintance only repository as far as libfg goes - I don't plan on adding any more features (since all the ones I need are there already). I will however work to produce a more pythonic interface to libfg, as the swig generated interface is a straight port of C api into Python.
Currently the repository contains the following fixes and enhancements:
- RGB565 and RGB555 patch by Adalbert Prokop
- fg_new_compatible_frame patch by echoline
- mmap fix by me
- swig generated Python interface by me
If you have a patch against libfg, please post it at the libfg project's page first, and then to me if Gavin does not respond. I do not intend to take over development of libfg, and it is my hope Gavin will in the future make this obselete/redundant.
Cheers,
Steve
Labels: c, code, computer, linux, oss, python, software
20080705
Another holiday, another webapp
Thats right, another webapp! This time using google's app engine, so feel free to abuse it, somewhat :P
Rank'em is its name, and it basically lets you create a collection of Things then allow other people to rank each Thing against each other, producing an overall ranking of Things.
Have fun and let me know what can be done better.
Cheers,
Steve
20080618
Personification of Programming languages 2
An follow up on the last round of language personifications, this time contributed by brett.
PHP
The crazy party girl you meet at Uni; she's easy to get along with at the beginning; she reminds you of other girls you've known before and hey, its a bit of fun; you're only young once. But after knowing her a few months the cracks begin to show; she's pretty inconsistent and while she tries to do favours for you and help you out, she ends up making it more complicated than it needed to be. The whole time you're with her, you have this sneaking suspicion that maybe you'd be better off with Perl, even if she's harder to speak to.
Javascript
The late bloomer; in high school she was pretty dorky; she couldn't do very much and while she might have spent time in different social circles, she could never really fit in. But now the puppy fat has dropped away and she's revealed herself to be one hell of a girl. She can do things you never would have expected a few years ago and suddenly she's the life of the party, appearing in places you never would have expected and doing things that make your jaw drop.
bash
The fat chick you picked up at that party, only because you were drunk and horny. You'd never tell your friends about it, but it got the job done, so to speak.
QBasic
Your first girlfriend in highschool. You were so nervous you didn't even end up kissing.
Many thanks again to brett for sharing these with us :-D
Cheers, Steve
20080428
{} I <3 thee
Firstly, I am the kind of guy who likes tabs over spaces, because I don't like forcing my particular preferences on to other people. To wax poetic, I like to give other people the freedom of choosing how they want their code indented. This of course brings me into the firing line of python programmers, for whom the 4-spaces-per-indentation-level is equivalent to the Ten Commandments handed down from Mount Sinai. Officially, python doesn't care, but thats like saying officially the Church accepts evolution.
I was editing a working python file written by some one else today, and wanted to convert it to tabs (yes yes, I know all about leaving files as I found them etc. Silence). So I ran unexpand -t 4 on the file. This simply replaces 4 spaces with one tab. This should have given me a working and correct python file though now indented with tabs. Naturally (Moore's law and all) this is not happened. The newly tab-indented file was riddled with errors because the original file was not indented properly so the simple conversion did not work. And as I go about fixing the errors python threw at me, I realised to my horror that information about the structure of the code was corrupted. Because python interprets code structure based on indentation, if your indentation is incorrect, your code is incorrect.
In comparison, a brace using language like C would have made the corrections trivial, because the braces explicitly specify the code structure. Python's argument that everyone indents anyway and thus braces are redundant is flawed - braces are not redundant because braces represent the separation of content from presentation, something that has been hammered into developers. In ignoring this, python has allowed a new class of errors - changing the appearance of code will now change the function of the code. I really can't see how this is a good thing.
If nothing else, python's integration of presentation and content, and thus presentation and program correctness makes it a far less robust language than brace using languages. Less robust in that a mangled python file is unrecoverable unless you actually read the code to figure out its structure, and that incorrectly transcribed python will likely run anyway with no syntactic or runtime errors.
Consider for example, the following code:
for n in names:
foo(n)
bar(n)
If you were transcribing the code and accidentally did not indent bar(n), the code now does something complete different yet no syntax or runtime error will be thrown. Now if the above code used braces, then it would have no effect. And if you forgot the brace, a syntax error will be thrown.
To be fair, python is a lovely language, and I do love it and use it extensively. Whitespace-as-syntax stance appeared at first to be a great idea, and one which now appears to be short sighted and naive. If nothing else, at least an interpreter which disallows incorrect space-indent files, that way tab->space and space->tab conversions would work correctly all the time.
Let me now put on my flame retardant undies, and you can flame away
Cheers,
Steve
Labels: code, computer, python, rant, software
20071231
html2pml
I was tired of converting all my HTML ebooks to rtf, then to pdb using Palm Doc Converter only to lose all the nice touches like bold, italics and headings. Since there didn't seem to be a HTML to PML converter for OS X, I wrote one to get more practice in python.
html2pml.py will convert basic HTML file to a PML file suitable for use with DropBook to be converted into a proper Palm ebook. I must stress the basic part - it only does stylistic conversions at the moment. I have no need for tables or links, so I didn't write them in. It does however do what I want - preserve bold and italic attributes, headings, and also translates some non-ascii characters into PML Extended Character Set, and to plain ascii where not possible.
This small python script is released under GPLv2, license is attached. If you find it useful, need more features, or have comments/suggestions, let me know!
Cheers,
Steve
20071213
Computing Oddities
Two strange and weird things happened to me recently. One is my /dev/null disappearing from leopard!
A large number of programs, both Cocoa and *nix relies on /dev/null being present. As you can see I could not gain root privileges, and thus could not recreate /dev/null (character device, 3,2). I had to in the end reboot and /dev/null was recreated.
Second strange thing is when I created a self-signed certificate for use with apache2 (for anonshare). I created it with openssl specifying 36500 for -days. The result is an certificate with expiration date in the past!
I am not aware of any X.509 specification regarding the number of days a certificate can be valid for, so I wonder - is this a bug in openssl?
Cheers,
Steve
20071122
Personification of Programming languages
The following personifications of programming languages came about while I was discussing various languages with my friends. Basically we started off with a description or sentence about a language, and I personified. In spirit it is the OS-tans but for programming languages
C
"Very fast, good at a few things, sucks at everything else". An autistic girl who is very good at maths. You will also need to keep sharp objects away from her because she is happy to run with scissors, so to speak. Does exactly as you tell her, even if it means grievous harm to herself or others. Needs to be kept in a padded room to avoid hurting herself and others.
C++
"I don't want code in it, but I can't help but like it". A girl who is so pretty you can't help but like her. Unfortunately she is also bat-shit insane, and will scratch your eyes out.
Python
"Very flexible, does everything easily and without complaint, but slow as hell". A girl who is flexible and easy going. Can do complicated contortions easily, an absolute joy to be with. Only thing is she is a bit thick.
Java
"Overtly verbose, unnecessarily strict, but pretty fast". She is one of those girls who you need to constantly buy gifts for in order to keep her satisfied. She will also continually talk non-stop about a variety of things, most of them inane. However she is of average intelligence and comes with a lot of accessories by default.
ASM
"Its like C, only dumber". Well thats it really. ASM is C-like, but even more autistic and a bit more dangerous.
Perl
"Well, its perl". Ah, perl. Perl is a girl like python, except she doesn't speak your language, and you don't speak her language. Over time the two of you have worked out a pidgin language which is a mismush of sign language, latin, french, foot stomping, hip gyrations, eye rolling, tongue poking, and so forth. No one else knows what you and perl are saying, and sometimes you don't even know what each other is saying and can only make wild guesses.
Thats all I have for now, will update when I have more to write :-)
Cheers,
Steve
20071104
Now you can all look and see how much I suck
Mactorii is now open sourced! GPLv2 for the curious. I haven't cleaned it up at all, which means be prepared to stab your eyes out with rusty fork after viewing the source. James told me not to bother, "cause then you will never release it". So blame James, its his fault/.
Cheers,
Steve
Labels: code
20070809
JAPH
not exp log srand xor s qq qx xor
s x x length uc ord and print chr
ord for qw q join use sub tied qx
xor eval xor print qq q q xor int
eval lc q m cos and print chr ord
for qw y abs ne open tied hex exp
ref y m xor scalar srand print qq
q q xor int eval lc qq y sqrt cos
and print chr ord for qw x printf
each return local x y or print qq
s s and eval q s undef or oct xor
time xor ref print chr int ord lc
foreach qw y hex alarm chdir kill
exec return y s gt sin sort split
Cheers,
Steve
Labels: code
20070716
Introducing SETerm
To learn a bit about using XCode, program in Objective-C using Cocoa and play with bluetooth and my phone, I wrote a simple bluetooth serial terminal. It simply connects to my phone (or any bluetooth device), opens a communication channel, and lets you send characters through it as if it is a serial connection. With my phone, this allows me to do pretty much everything that - list, read, send SMSs, contacts, check battery status, signal strength, etc.
Nifty! Here is a picture:
Download it, give it a whirl. I will one day update it to use Core Data so it handles SMSs and contacts in a nicer way then dumping out as text.
Cheers,
Steve
Labels: code
20070414
Writing fitting functions for lmfit
double function_name(double, double *);
For example:
double sin_fit(double t, double * p)
{
return p[0] + p[1] * sin ( 2 * M_PI * ( p[2] * t + p[3]));
}
Note that while lm_minimize takes a pointer to an array of parameters, it may not always pass that pointer to the fitting function. Because of this passing fixed parameters to the fitting function using the 3rd argument will yield incorrect results. For example, the following code is wrong:
double wrong_fit(double t, double *p)
{
return p[0]*p[0] + p[1];
}
....
double p[2];
p[0] = 1;
p[1] = magic_number;
...
lm_minimize(..., 1, p, ..., ..., ...., ...);
Here the fitting function wrong_fit relies on a fixed parameter p[1] which it expects to contain the value magic_number. However it will be passed such a p that only p[0] has a valid value and p[1] is undefined. This will lead to incorrect operation.
To work around this, you can use global variables, as follows:
double magic = magic_number;
...
double right_fit(double t, double * p)
{
return p[0]*p[0] + magic;
}
....
double p = 1;
...
lm_minimize(..., 1, &p, ..., ..., ..., ...);
Cheers,
Steve
20060318
Fourier fitting with gnuplot
gnuplot can be used to fit a fourier series to a series of data points. In my case it was an observation log for the star BE Lyncis from the Bossom Observatory, curtsey of Geir Klingenberg.
Firstly one needs to define a time function t(x) such that as x progresses from its minimum value to its maximum value t(x) ranges from 0 to 2PI. In my case minimum value of x was 2453416.20172 and maximum value was 2453416.42447. So my t(x) was constructed as follows:
We now need to define a fourier series, f(x). It takes the generic form of:
Where #=0,1,2,3... infinity, and is the degree of the fourier series. Now we can use gnuplot's fit function to determine the values of all co-efficients and the constant c:
A quick explanation: we are trying to fit f(t) where t=t(x) using data from the file be_lyn-2005.txt with data from the first and second column. The order of 1:2 is significant as it is in the form of x:y. Thus 2:1 means the first column is y value, second column is x value. (This is from experience, if any one knows better, tell me!)
Co-efficient values and the constant will be computed and shown, along with various statistic data. An plot of the fourier series and the observed data is shown below.
The plain text file be_lyn-2005.txt has 3 columns: JD, instrumental magnitude, and error estimate, the later of which was not used.
Cheers,
Steve
Labels: astronomy, code, computer, oss, science, software
20040714
Downloads
- html2pml
Converts simple html to pml
Features
- Works where python is available
- Works pretty well :-)
- Preserves bold and italic
- Small
- Works :D
- Portable to almost everything under the Sun
- Outputs in a format that can be easily pasted into mathpad or matlab for plotting
- Small
- Fast
- Portable to almost everything under the Sun
- Command line based
- Easily scriptable
- Works!
- Command line based
- Flexible format string
- up to 8 numerical replacements
- DNS lookup to reduce false positives
- Makes you hate me
- Opengl accelerated
- In game console
- GlUT library for portability
- Sorts files into directories based on specified fields of ID3v1/2 tag
- Sorts incrementally by artist/song/genre/album/etc, in any order
- File renamer to rename songs based on ID3v1 tag information
- File renamer supports format strings to create your own combination
- ID3Tag removal utility to remove ID3Tags
- Can be applied to entire directories
- ID3Tag Editor with single and multiple file support
- Can add id3v1 tags to files that doesn't have them
- Very cool busy animation :)
- Extensive online documentation included
- Opengl accelerated
- Scripting support
- Motion blurr
- Induces motion sickness in some ;)
- Command line based
- Detects unique, parametric solutions, as well as no solutions
- Prints unique and parametric solutions
- Works! :)
- Will print out working
- Small
- Command line based
- (Auto)scaling



