Historical note. As originally conceived,
the taxonomic tree was stored within the
class in an attribute named
.root that contained
Taxon instance representing the root taxon
(Class Aves). So that we can support lookup of taxa by
scientific name or taxonomic key number, we must maintain two
dictionaries along with the tree that map scientific name and
key number to the corresponding taxon.
The operation of adding a taxon to the tree occurs in two places. Most are added while reading the standard forms file. However, subspecific taxa are added to the tree during processing of the alternate forms file. In the Cleanroom intended functions for this operation, three state items were affected: the tree itself, the scientific name map, and the taxonomic key map. The whole point of using classes to create abstract data types is to hide this kind of detail.
Therefore, the taxonomic tree and its associated dictionaries
were moved to this new class,
TaxaTree. A number
of methods that were originally in the
are here because they pertain to the tree, rather than to the
bird code system.
Here is the interface:
# - - - - - c l a s s T a x a T r e e class TaxaTree(object): '''Represents the strictly taxonomic tree. Exports: TaxaTree ( hier ): [ hier is a Hier instance -> return a new, empty TaxaTree instance using the ranks from hier ] .hier: [ as passed to constructor, read-only ] .root: [ if self is empty -> None else -> the root taxon as a Taxon instance with rank.depth==0, and rooting a tree such that children of any node have depth greater than that of their parent, all the children of a node have the same depth, and the children of a node may not be deeper than the shallowest required rank deeper than that of the parent ] .setRoot ( taxon ): [ taxon is a Taxon instance -> if (self is empty) and (taxon's depth is 0) -> self := self with taxon as its root else -> raise ValueError ] .rankParent ( newRankCode ): [ newRankCode is the code for a rank in self.hier -> if a taxon of that rank can be added to self as its last node in preorder -> return rank-parent ( self, that rank ) else -> raise ValueError ] .canAddChild ( parent, childRankCode ): [ (parent is a Taxon in self) and (childRankCode is the code of a Rank in self.hier) -> if can-add-child(self.hier, parent, that rank) -> return None else -> raise ValueError ] .addTaxon ( parent, rawTaxon ): [ (parent is a taxon in self, or None for the root) and (rawTaxon is a RawTaxon instance) and (can-add-child(parent, rawTaxon)) -> parent := parent with a new child Taxon added, made from rawTaxon return that new Taxon ] .lookupTxKey ( txKey ): [ txKey is a string -> if txKey matches the taxonomic key of a taxon in self -> return that taxon else -> raise KeyError ] .__getitem__ ( sci ): [ sci is a string -> if sci matches the name of a taxon in self -> return that taxon else -> raise KeyError ] .__contains__(self, sci): [ if sci is a scientific name in self -> return True else -> return False ] .writeXML ( parent ): [ parent is an et.Element -> parent := parent with an rnc.TAXONOMY_N element added representing self's taxonomic tree ]
Here are the internals of the class.
State/Invariants: .__sciMap: [ a dictionary whose keys are the scientific names of the taxa in self, and each related value is that Taxon instance ] .__txKeyMap: [ a dictionary whose keys are the taxonomic key numbers of the taxa in self, and each related value is that Taxon instance ] '''