# - - - T x n y . _ _ a d d S p e c i e s def __addSpecies ( self, scan, stdHead, spTail ): '''Add a new species taxon and its bindings. [ (scan is a Scan instance) and (stdHead is a StdHead instance) and (spTail is an SpTail instance) -> if (stdHead, spTail) names a species that can be appended to self.taxaTree -> self.taxaTree +:= a new Taxon for that species self.abTab +:= bindings from (stdHead, spTail) else -> self.taxaTree +:= a new Taxon for that species, if valid Log() +:= error message(s) raise SyntaxError ] '''
There is one subtle input error that we need to detect. Suppose someone prepares a standard forms file in which the species in a particular genus are not all together in sequence, like this:
f Famiday Ardea cinerea/... Egretta thula/... Ardea herodias/...
If we use the standard placement rules, species herodias would be placed in the wrong genus, Egretta, because that genus is the growing point for adding new species! There is a parallel problem for subgenera.
The solution is to calculate the genus or subgenus parent of
the species using Section 18.3, “
TaxaTree.rankParent(): Under what parent
does a new taxon go?”. If the
parent is a genus, its name must match
spTail.genus; if the parent is a subgenus, its name
spTail.subgenus. For the relevant
intended function, see Section 7.9, “
rank-parent: What taxon is the parent
of a new taxon of a given rank?”.
#-- 1 -- # [ parent := rank-parent ( self.taxaTree, SPECIES_CODE ) # sci := spTail.genus + " " + spTail.species ] parent = self.taxaTree.rankParent ( SPECIES_CODE ) sci = "%s %s" % (spTail.genus, spTail.species) #-- 2 -- # [ if parent matches genus or subgenus from spTail -> # I # else -> # Log() +:= error message(s) # raise SyntaxError ] if parent.rank.code == GENUS_CODE: expectSci = spTail.genus else: expectSci = "%s (%s)" % (spTail.genus, spTail.subgenus) if parent.sci != expectSci: scan.syntax ( "One expects to place this species in '%s', " "but you have it in '%s'." % (parent.sci, expectSci) )
Assemble the new species's attributes into a
RawTaxon instance, then append it to the tree
(assuming that it fits). See Section 23, “
class RawTaxon: Temporary container for
taxon attributes” and Section 17.7, “
Txny.__appendTaxon(): Try to append this
taxon to the tree”.
#-- 3 -- # [ rawSpecies := a new RawTaxon instance with rank code # SPECIES_CODE; scientific name (sci); English name # (spTail.eng); status (spTail.status); # canon (spTail.canonical); and disambiguation # (spTail.disamb) ] rawSpecies = RawTaxon ( SPECIES_CODE, sci, spTail.eng, stdHead.status, spTail.canonical, spTail.disamb ) #-- 4 -- # [ if rawSpecies can be appended to self.taxaTree -> # self.taxaTree +:= a new Taxon instance made from rawTaxon # taxon := that new Taxon # else -> # Log() +:= error message(s) # raise SyntaxError ] taxon = self.__appendTaxon ( scan, rawSpecies )
Unlike the genus and subgenus case, a species can carry one or two new bird code bindings; add them to the symbol table.
#-- 5 -- # [ if the bindings for taxon are consistent with self.abTab -> # self.abTab +:= those bindings # else -> # Log() +:= error message(s) # raise SyntaxError ] self.__addCodes ( scan, taxon )