Source code for commonnexus.blocks.notes

import typing

from .base import Block, Payload
from commonnexus.tokenizer import iter_key_value_pairs, Word

if typing.TYPE_CHECKING:  # pragma: no cover
    from commonnexus.nexus import Nexus


[docs]class Text(Payload): """ This command allows text to be attached to various objects. The SOURCE subcommand indicates the location of the text. The INLINE option indicates that the text is present at the end of the TEXT command; the FILE option indicates that it is in a separate file (the name of which is then specified in the TEXT subcommand); the RESOURCE option indicates that it is in the resource fork of the current file, in a resource of type TEXT (the numerical ID of which is then specified in the TEXT subcommand). For example, in the following .. code-block:: TEXT TAXON=5 CHARACTER=2 TEXT='4 specimens observed'; TEXT TAXON=Pan TEXT='This genus lives in Africa'; TEXT CHARACTER=2 TEXT='Perhaps this character should be deleted'; TEXT CHARACTER=1 STATE=0 TEXT='This state is hard to detect'; the first command assigns the note "4 specimens observed" to the data entry for taxon 5, character 2; the second command assigns the note "Perhaps this character should be deleted" to character 2; the third command assigns the note "This genus lives in Africa" to the taxon Pan, and the last command assigns the note "This state is hard to detect" to state 0 of character 1. The text or source descriptor must be a single NEXUS word. If the text contains NEXUS whitespace or punctuation, it needs to be surrounded by single quotes, with any contained single quotes converted to a pair of single quotes. :ivar typing.List[str] taxons: list of taxon labels or numbers the text relates to. """ def __init__(self, tokens=None, nexus=None, **kw): super().__init__(tokens, nexus=nexus) self.taxons = None self.characters = None self.states = None self.trees = None self.source = None self.text = None if self._tokens is None: for k, v in kw.items(): setattr(self, k, v) else: for key, values in iter_key_value_pairs(self._tokens): key = key.lower() if key in ['taxon', 'character', 'state', 'tree']: key = key + 's' else: assert len(values) == 1 values = values[0] setattr(self, key.lower(), values) if self.nexus: for key in ['taxon', 'character', 'state', 'tree']: key = key + 's' if getattr(self, key): kw = {} if key == 'states': kw['chars'] = self.characters setattr(self, key, self.nexus.resolve_set_spec( key[:-1].upper(), getattr(self, key), **kw)) assert self.source in [None, 'FILE', 'INLINE'], self.source def as_payload(self): res = [] if self.taxons: numbers = ' '.join( self.nexus.get_numbers('TAXON', self.taxons) if self.nexus else self.taxons) res.append("TAXON={}".format('({})'.format(numbers) if ' ' in numbers else numbers)) if self.characters: numbers = ' '.join(self.nexus.get_numbers('CHARACTER', self.characters) if self.nexus else self.characters) res.append("CHARACTER={}".format('({})'.format(numbers) if ' ' in numbers else numbers)) # # FIXME: support STATE! # if self.trees: numbers = ' '.join( self.nexus.get_numbers('TREE', self.trees) if self.nexus else self.trees) res.append("TREE={}".format('({})'.format(numbers) if ' ' in numbers else numbers)) res.append('SOURCE=INLINE') res.append('TEXT={}'.format(Word(self.text).as_nexus_string())) return ' '.join(res)
[docs]class Picture(Payload): """ This command allows a picture to be attached to an object. The FORMAT subcommand allows specification of the graphics format of the image. The SOURCE subcommand indicates the location of the picture. The INLINE option indicates that the picture is present at the end of the PICTURE command; the FILE option indicates that it is in a separate file (the name of which is then specified in the PICTURE subcommand); the RESOURCE option indicates that it is in the resource fork of the current file, in a resource of type PICT (the numerical ID of which is then specified in the PICTURE command). The RESOURCE option is designed for AppleMacintosh® text files. For example, the following command .. code-block:: PICTURE TAXON=5 CHARACTER=2 FORMAT=GIF SouRCE=file PiCTURE=wide.thorax.gif; assigns the image in the GIF-formatted file wide.thorax.gif to the data entry for taxon 5, character 2. The picture or source descriptor must be a single NEXUS word. If the picture contains NEXUS whitespace or punctuation, it needs to be surrounded by single quotes, with any contained single quotes converted to a pair of single quotes. Most graphics formats do not describe pictures using standard text characters. For this reason many images cannot be included INLINE in a NEXUS command unless they are converted into text characters. The ENCODE subcommand specifies the conversion mechanism used for inline images. .. warning:: Support for encoding of type ``UUENCODE`` will be removed in Python 3.13, because `base64 is a modern alternative <https://docs.python.org/3/library/uu.html>`_ """
[docs]class Notes(Block): """ The NOTES block stores notes about various objects in a NEXUS file, including taxa, characters, states, and trees: .. rst-class:: nexus | BEGIN NOTES; | [TEXT | [TAXON=taxon-set] | [CHARACTER=character-set] | [STATE=state-set] | [TREE=tree-set] | SOURCE={INLINE | FILE | RESOURCE} TEXT=text-or-source-descriptor;] | [PICTURE | [TAX0N=taxon-set] | [CHARACTER=character-set] | [STATE= state-set] | [TREE=tree-set] | [FORMAT={PICT | TIFF | EPS | JPEG | GIF}] | [ENCODE={NONE | UUENCODE | BINHEX}] | SOURCE={INLINE | FILE | RESOURCE} | PICTURE=picture-or-source-descriptor; ] | END; There are no restrictions on the order of commands. If the written description of the taxon-set, character-set, state-set, or tree-set contains more than one token, it must be enclosed in parentheses, as in the following example: .. code-block:: TEXT TAXON=(1-3) TEXT= 'these taxa from the far north'; If both a taxon-set and a character-set are specified, then the text or picture applies to those characters for those particular taxa. If both a character-set and a state-set are specified, then the text or picture applies to those states for those particular characters. .. warning:: PICTURE and ``SOURCE=RESOURCE`` for TEXT is not supported by `commonnexus`. """ __commands__ = {Text, Picture}
[docs] @classmethod def from_data(cls, texts: typing.List[typing.Dict[str, typing.Union[typing.List[str], str]]], comment: typing.Optional[str] = None, nexus: typing.Optional["Nexus"] = None, TITLE: typing.Optional[str] = None, ID: typing.Optional[str] = None, LINK: typing.Optional[typing.Union[str, typing.Tuple[str, str]]] = None) \ -> 'Block': cmds = [('TEXT', Text(nexus=nexus, **text).as_payload()) for text in texts] return cls.from_commands(cmds, nexus=nexus, TITLE=TITLE, ID=ID, LINK=LINK, comment=comment)
@property def texts(self): return self.commands['TEXT'] def get_texts(self, taxon=None, character=None, tree=None): res = [] for text in self.texts: if (taxon and text.taxons and taxon in text.taxons) or \ (character and text.characters and character in text.characters) or \ (tree and text.trees and tree in text.trees): res.append(text) return res