4.3.4 Text Files

The NewPedigree::save() method writes a PyPedal pedigree to a user-specified file based on a pedigree format string and optional column separator provided by the user. By default, the pedformat is "asd" and the sepchar is " ". Any attribute of a NewAnimal object can be written to an output file.

NewPedigree::save() tries never to overwrite your data. If you do not pass a filename argument a file whose name is derived from, but not the same as, the original pedigree filename will be used. The string "_saved" will be appended to the filename in order to distinguish it from the original pedigree file.

There are a few points that you need to be aware of when using NewPedigree::save(). First, you may use any column separator you choose but the empty string (sepchar=''); if you try and do this the sepchar will be changed to the global default (currently " "), and a message written to the log. That means that there is no way for you to run all of the columns in your pedigree file together such that they cannot easily be separated. Sorry. You can use anoy other string you like to separate your columns (spaces, columns, and tabs have been tested).It IS possible to write an incomplete pedigree file, that is, a file which does not include animal, sire, and dam information. PyPedal checks the pedformat to see if it contains either 'asd' or 'ASD' and warns you if it does not, but it will happily write the file you tell it to. The burden is on you, the user, to make sure that your output file contains all of the information you want. Finally, you can write whatever attribute you like to whichever column you like in the output file. For the sake of your sanity I strongly recommend that you always place the animal, sire, and dam IDs in the first three columns, but you're an adult and may do what you like.

Maybe a couple of examples will help clear that up. Here's the simplest case, taking defaults:

test.save('test_save_asd.ped')
gets you the result:
# test_save_asd.ped created by PyPedal at Tue Sep 28 16:39:36 2010
# Current pedigree metadata:
#       pedigree file: test_save_asd.ped
#       pedigree name: Untitled
#       pedigree format: asd
#       NOTE: Animal, sire, and dam IDs are RENUMBERED IDs, not original IDs!
# Original pedigree metadata:
#       pedigree file: ../simulated_pedigree.ped
#       pedigree name: Untitled
#       pedigree format: asdxg
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
...
21 19 10
22 9 12
23 1 10
24 1 21
25 13 8
Note the friendly header to tell you what you've got and from where it came. The note about renumbere IDs is particularly important - if the pedigree_is_renumbered flag is set then you will get this message to alert you that comparing this file against your original source file may give conflicting results. Well, they're not really conflicting, but if you compare renumbered with not-renumbered IDs the you may assume there's some kind of problem when really there is not. Original and renumbered pedigrees are mathematically equivalent assuming that there were no errors in the original file that were corrected by PyPedal. Isn't that reassuring? From here on out I will not show the header, and will include only the first five data rows in the file for the sake of brevity (like I've ever let that stop me before). You can get the same thing as a CSV using the sepchar argument:
test.save('test_save_asd_csv.ped', sepchar=',')
which produces:
1,0,0
2,0,0
3,0,0
4,0,0
5,0,0
...
Sometimes you want to go all the way and dump everything into a file. This is like one of those pizzas with every variety of cured meat known to food science piled up on top. Here you go:
test.save('test_save_combo_all.ped', pedformat = 'asdgxbfrnylepASDLhHu')
which gives you what you asked for, even if many of the values are not particularly interesting:
1 0 0 0 m 01011900 0.0 Unknown_Breed 7 1900 0 -999 -999.0 7 Unknown_Name Unknown_Name ['1900000000000000071__1', '1900000000000000071__2'] 57361b5fd9993f00437fbe4c4675feca Unknown_Herd
2 0 0 0 m 01011900 0.0 Unknown_Breed 6 1900 0 -999 -999.0 6 Unknown_Name Unknown_Name ['1900000000000000061__1', '1900000000000000061__2'] 57361b5fd9993f00437fbe4c4675feca Unknown_Herd
3 0 0 0 m 01011900 0.0 Unknown_Breed 5 1900 0 -999 -999.0 5 Unknown_Name Unknown_Name ['1900000000000000051__1', '1900000000000000051__2'] 57361b5fd9993f00437fbe4c4675feca Unknown_Herd
4 0 0 0 f 01011900 0.0 Unknown_Breed 3 1900 0 -999 -999.0 3 Unknown_Name Unknown_Name ['1900000000000000031__1', '1900000000000000031__2'] 57361b5fd9993f00437fbe4c4675feca Unknown_Herd
5 0 0 0 f 01011900 0.0 Unknown_Breed 2 1900 0 -999 -999.0 2 Unknown_Name Unknown_Name ['1900000000000000021__1', '1900000000000000021__2'] 57361b5fd9993f00437fbe4c4675feca Unknown_Herd
...
Okay, I get it. You're like the Nigel Tufnel of Missouri - you want to see something that goes to 11. I pondered this for a while. You've read this far and deserve to be rewarded. So I tried to think of the most awesomest thing that I could think of. So here you go, LSU fans, straight from Death Valley by way of Beltsville, MD:
test.save('test_save_peterson.ped', pedformat = 'asd', sepchar = '...Kneel before Zod!...'
Maybe Patrick Peterson is really into genealogy - you never know - stop looking at me like that! This is a perfectly cromulent example of the extremes to which the sepchar argument can be pushed:
1...Kneel before Zod!...0...Kneel before Zod!...0
2...Kneel before Zod!...0...Kneel before Zod!...0
3...Kneel before Zod!...0...Kneel before Zod!...0
4...Kneel before Zod!...0...Kneel before Zod!...0
5...Kneel before Zod!...0...Kneel before Zod!...0
...
You're thinking, "My eyes! Why would he do that?!" The same reason Zod gave us a little Heisman pose in the end zone after returning a West Virginia kickoff for 6 - because I can. (This kind of writing is probably going to get me in trouble one day, but the boss is out of town and there's no one here to rein-in my behavior!) Wait, though. It gets better. PyPedal can get all Ourboros on this unholy creation:
# But, wait, can this actually work?
options2 = options
options2['pedfile'] = 'test_save_peterson.ped'
options2['sepchar'] = '...Kneel before Zod!...'
options2['pedformat'] = 'asd'
test2 = pyp_newclasses.loadPedigree(options2)
When you run this bit of code you see that it poses no problem at all for PyPedal. Perhaps political dissidents can communicate secretly by doing strange things with sepchar, although it's more likely that PhD students will find a clever way to abuse MS students with it, instead.
[INFO]: Logfile untitled_pedigree.log instantiated.
[INFO]: Preprocessing test_save_peterson.ped
[INFO]: Opening pedigree file test_save_peterson.ped
        [INFO]: Renumbering pedigree at Wed Sep 29 13:42:05 2010
                [INFO]: Reordering pedigree at Wed Sep 29 13:42:05 2010
                [INFO]: Renumbering at Wed Sep 29 13:42:05 2010
                [INFO]: Updating ID map at Wed Sep 29 13:42:05 2010
        [INFO]: Assigning offspring at Wed Sep 29 13:42:05 2010
[INFO]: Creating pedigree metadata object
        [INFO]:  Instantiating a new PedigreeMetadata() object...
        [INFO]:  Naming the Pedigree()...
        [INFO]:  Assigning a filename...
        [INFO]:  Attaching a pedigree...
        [INFO]:  Setting the pedcode...
        [INFO]:  Counting the number of animals in the pedigree...
        [INFO]:  Counting and finding unique sires...
        [INFO]:  Counting and finding unique dams...
        [INFO]:  Setting renumbered flag...
        [INFO]:  Counting and finding unique generations...
        [INFO]:  Counting and finding unique birthyears...
        [INFO]:  Counting and finding unique founders...
        [INFO]:  Counting and finding unique herds...
        [INFO]:  Detaching pedigree...
Metadata for Untitled (test_save_peterson.ped)
        Records:                25
        Unique Sires:           7
        Unique Dams:            7
        Unique Gens:            1
        Unique Years:           1
        Unique Founders:        6
        Unique Herds:           1
        Pedigree Code:          asd
How's that for the strangest thing you're likely to see all day? I'm not suggesting that you seriously use column separators the way I just did, but this example does show that you can do some unusual things with PyPedal, and perhaps you will come up with something very useful because of that flexibility. If nothing else, you now have a greater appreciation of what you can do with a dynamic language and questionable processing of user inputs. Remember, never trust any data a user gives you. They're a shifty lot, users.

See About this document... for information on suggesting changes.