Пример #1
0
 def end(cls, exception=''):
     """Calls method to perform necessary steps for clean exit."""
     Plot.end()
     if exception:
         Log.add(str(exception))
     Log.add('Exiting program')
     Log.print()
     exit()
Пример #2
0
    def end(cls):
        """Terminates graphics engine cleanly"""

        curses.nocbreak()
        cls.scr.keypad(False)
        curses.echo()
        curses.endwin()
        Log.add('Terminated plotter')
Пример #3
0
 def init(cls,locked):
     cls.uis["static"] = Static_Window(16,0)
     cls.uis["left"] = Panel(["Info", "Minerals", "Elevation","Humidity"],"left")
     cls.uis["right"] = Panel(["Build", "Select","Remove"],"right")
     cls.uis["info"] = Widget([{'label':'Height: ','value':0},
                               {'label':'Minerals: ','value':0},
                               {'label':'Humidity: ','value':0}])
     cls.locked = locked
     cls.view = "Elevation"
     cls.string_repr = "Terrain State - " + cls.view
     Log.add('State set to terrain')
Пример #4
0
 def init(cls):
     cls.string_repr = "Main State"
     cls.uis["static"] = None
     cls.uis["left"] = Panel(["Ships", "Production","Resources"],"left")
     cls.uis["right"] = Panel(["Colonies","Research","Pause"],"right")
     cls.uis["bottom"] = Panel(["Next Turn"],"bottom")
     cls.uis["top"] = Panel(["Map", "Info","Ship","Battle","Tech"],"top")
     cls.lock = False
     middle = [i//2 for i in Board.size]
     cls.posx,cls.posy = middle[0],middle[1]
     cls.panx,cls.pany = Board.size[0] - int(Plot.x /2), 18 + int(0.5 * ((Board.size[1] - int(Plot.y *2)))) 
     Log.add('State set to map')
Пример #5
0
 def move(cls,x1,y1,x2,y2):
     """Move object in terrain[x1][y1] to terrain[x2][y2]."""
     
     #TODO: Move logic to logic.py
     distance = dist(x1,y1,x2,y2)
     if cls.terrain[x2][y2].search():
         Log.add("Ship movement failed, obstacle detected.")
         pass
     elif distance <= cls.terrain[x1][y1].fuel:
         Log.add("Moving ship from (" + str(x1) + ","+str(y1) +") to ("+ str(x2) + ","+str(y2)+")")
         cls.terrain[x2][y2] = cls.terrain[x1][y1]
         cls.terrain[x1][y1] = Empty()
         cls.terrain[x2][y2].deplete(distance)
Пример #6
0
    def handle_input(cls):
        """Takes the key pressed by the user and calls the appropiate method.
        
        Bindings:
            q       -- Quits game / Quits Menu
            w,a,s,d -- Moves cursor / UI Selection
            e       -- locks and unlocks cursor / Accept
            t y u
            g h j
            b n m
        """
        #change will be False if there is no need to change stage
        #if there is, change[0] will contain a string indicating either the stage
        #or an instruction for moving in the stage chain (like "back")
        #further indexes will contain the necessary arguments for the transition, like the object

        key = cls.get_input()

        change = cls.state.handle_input(key)
        if change:
            if change[0] == "end":
                cls.end()

            elif change[0] == "terrain":
                cls.state = State_Terrain
                cls.state_chain.append(cls.state)
                cls.state.init(change[1])

            elif change[0] in ["Minerals", "Humidity", "Elevation", "Info"]:
                cls.state = State_Terrain
                cls.state_chain[-1] = cls.state
                cls.state.change_view(change[0])

            elif change[0] in ["Build", "Select", "Remove"]:
                cls.state.change_action(change[0])

            elif change[0] == "back":
                cls.state_chain = cls.state_chain[:-1]
                cls.state = cls.state_chain[-1]

            elif change[0] == "main":
                cls.state_chain = cls.state_chain[0]
                cls.state = cls.state_chain[0]

            Log.add(str(cls.state_chain))
Пример #7
0
class TestLog(unittest.TestCase):
    def setUp(self):
        self.client = Redis(decode_responses=True)
        self.client.flushdb()

        self.log = Log(self.client, '25, March')

        self.log1 = "03:00 server up online"
        self.log2 = "03:15 handle request 1"
        self.log3 = "03:16 handle request 2"

    def test_add_works(self):
        self.assertTrue(len(self.log.get_all()) == 0)

        self.log.add(self.log1)

        self.assertTrue(len(self.log.get_all()) == 1)

    def test_get_all_works(self):
        self.assertEqual(self.log.get_all(), [])

        self.log.add(self.log1)
        self.log.add(self.log2)
        self.log.add(self.log3)

        result = self.log.get_all()

        self.assertEqual(self.log1, result[0])

        self.assertEqual(
            self.log2,
            result[1],
        )

        self.assertEqual(self.log3, result[2])
Пример #8
0
 def start(cls):
     """Initializes graphics engine, and returns an instance of the curses Screen class.
     
     Sets starting positions for cursor and camera, initializes color profiles and terminal settigs.
     """
     scr = curses.initscr()
     curses.noecho()
     curses.cbreak()
     curses.start_color()
     curses.use_default_colors()
     scr.keypad(True)
     curses.init_pair(1, curses.COLOR_RED, -1)
     curses.init_pair(2, curses.COLOR_BLUE, -1)
     curses.init_pair(3, curses.COLOR_GREEN, -1)
     curses.init_pair(4, curses.COLOR_WHITE, -1)
     curses.init_pair(5, curses.COLOR_BLACK, 7)
     scr.clear()
     cls.y, cls.x = scr.getmaxyx()
     cls.y -= 1
     Log.add(str(cls.x))
     cls.scr = scr
     Log.add('Plotter initialized')
Пример #9
0
 def start(cls,star_radius):
     cls.terrain = [[Empty() for i in range(cls.size[1])] for j in range(cls.size[0])]
     cls.gen_star(star_radius)
     cls.gen_planets(int(Config.config['Constants']['CantPlanets']))
     cls.spawn_tests()
     Log.add('Board initialized')
Пример #10
0
class Morph:
    # These are the allowed properties of a morph object. Values not specified
    # by user are set to None
    # This is an Abstract Object representing the Morph of a metabolic model
    # from one species to a close relative genome. It has information related to
    # the source model, the target genome, the reactions in the model as it is
    # morphed from source import to target, and the set of
    properties = {
        'src_model', 'genome', 'probanno', 'protcomp', 'model', 'rxn_labels',
        'ws_id', 'ws_name', 'trans_model', 'recon_model', 'media', 'probhash',
        'log', 'merge_conflicts', 'service'
    }

    def __init__(self, *arg_hash, **kwargs):
        """
        Initiializes a Morph! A Morph needs each of the following set:
            src_model: (FBAModel) the model of the source organism
            genome: (Genome) the genome of the target organism
            probanno: (ReactionProbabilities) the likelihoods for KBase reactions in the target organism
            protcomp: (ProteomeComparison) the proteome comparison between source and target genomes
            media: (Media) the media for the source model and subsequent models
        :param arg_hash: a dictionary with the attributes desired as keys
        :param kwargs: keyword arguments
        :return:
        """
        self.src_model = None
        self.model = None
        self.genome = None
        self.probanno = None
        self.protcomp = None
        self.model = None
        self.rxn_labels = None
        self.media = None
        self.recon_model = None
        self.trans_model = None
        self.probhash = None
        self.log = None
        self.ws_id = None
        self.ws_name = None
        self.essential_ids = None
        self.removed_ids = None
        self.service = None

        for dictionary in arg_hash:
            for key in dictionary:
                if key in Morph.properties:
                    setattr(self, key, dictionary[key])
        for key in kwargs:
            if key in Morph.properties:
                setattr(self, key, kwargs[key])
        for prop in Morph.properties:
            if not hasattr(self, prop):
                setattr(self, prop, None)
        if self.log is None:
            self.log = Log(self)
        if self.ws_id is None:
            raise ValueError()
        self._check_rep()

    def _check_rep(self):
        if self.model is not None:
            assert isinstance(self.model, FBAModel), str(type(self.model))
        if self.src_model is not None:
            assert isinstance(self.src_model,
                              FBAModel), str(type(self.src_model))
        if self.genome is not None:
            assert isinstance(self.genome, Genome), str(type(self.genome))
        if self.media is not None:
            assert isinstance(self.media, Media), str(type(self.media))
        if self.probanno is not None:
            assert isinstance(self.probanno,
                              ReactionProbabilities), str(type(self.probanno))
        if self.protcomp is not None:
            assert isinstance(self.protcomp,
                              ProteomeComparison), str(type(self.protcomp))
        if self.trans_model is not None:
            assert isinstance(self.trans_model,
                              FBAModel), str(type(self.trans_model))
        if self.recon_model is not None:
            assert isinstance(self.recon_model,
                              FBAModel), str(type(self.recon_model))

    def to_json(self, filename=None):
        data = {}
        for prop in Morph.properties:
            val = self.__dict__[prop]
            if hasattr(self, prop) and val is not None:
                if isinstance(val, StoredObject):
                    data[prop] = self.__dict__[prop].to_json()
                elif isinstance(val, Log):
                    data[prop] = val.to_json()
                else:
                    data[prop] = val
        if filename is not None:
            with open(filename, 'w') as f:
                f.write(json.dumps(data))
        else:
            return json.dumps(data)

    @staticmethod
    def from_json(json_str):
        data = json.loads(json_str)
        args = {}
        for key in data:
            if key in {'src_model', 'model', 'recon_model', 'trans_model'}:
                args[key] = FBAModel.from_json(data[key])
            elif key == 'genome':
                args[key] = Genome.from_json(data[key])
            elif key == 'protcomp':
                args[key] = ProteomeComparison.from_json(data[key])
            elif key == 'probanno':
                args[key] = ReactionProbabilities.from_json(data[key])
            elif key == 'media':
                args[key] = Media.from_json(data[key])
            elif key == 'log':
                args[key] = Log.from_json(data[key])
            else:
                args[key] = data[key]
        return Morph(args)

    @staticmethod
    def from_json_file(filename):
        with open(filename, 'r') as f:
            return Morph.from_json(f.read())

    # Overridden Functions to produce unique output
    def __str__(self):
        output = ''
        for key in vars(self):
            attr = getattr(self, key)
            if isinstance(attr, dict):
                attr = attr.keys()
                if len(attr) < 100:
                    output += str(key) + ': ' + str(attr) + '\n'
                else:
                    output += str(key) + ': ' + str(
                        attr[0:100]) + ' ... (more)\n'
            else:
                output += str(key) + ': ' + str(attr) + '\n'
        return output

    def __repr__(self):
        return str(self)

    def __unicode__(self):
        return unicode(str(self))

    def fill_src_to_media(self):
        """
        Gap-fills the Morphs source model to the provided media
        :return: None
        """
        prev = FBAModel(self.src_model.object_id,
                        self.src_model.workspace_id,
                        service=self.service)
        self.src_model = self.src_model.copy(self.service,
                                             workspace_id=self.ws_id)
        result = self.service.gapfill_model(self.src_model,
                                            self.media,
                                            workspace=self.ws_id)
        self.src_model = FBAModel(result[0], result[1], service=self.service)
        self.log.add('gapfill',
                     prev,
                     self.src_model,
                     context='fill_src_to_media')

    def runfba(self, model=None, media=None):
        """
        Run FBA on the model in the Morph
        :param model: (optional) FBAModel, default is morph.model
        :param media: (optional) Media, default is morph.media
        :return: FBA
        """
        if model is None:
            model = self.model
        if media is None:
            media = self.media
        objid, wsid = self.service.runfba(model, media, self.ws_id)
        return FBA(objid, wsid, service=self.service)

    def translate_features(self):
        """
        Translate morph.model using ProteomeComparison (morph.procomp) to a translated model
        :return: None (sets morph.trans_model)
        """
        prev = copy.deepcopy(self.trans_model)
        result = self.service.translate_model(self.src_model,
                                              self.protcomp,
                                              workspace=self.ws_id)
        self.trans_model = FBAModel(result[0], result[1], service=self.service)
        self.log.add('model_translation',
                     prev,
                     self.trans_model,
                     context='translate_features')

    def reconstruct_genome(self):
        """
        Reconstruct the genome using automated reconstruction in the service form morph.genome
        :return: None (sets morph.recon_model)
        """
        prev = copy.deepcopy(self.recon_model)
        result = self.service.reconstruct_genome(self.genome,
                                                 workspace=self.ws_id)
        self.recon_model = FBAModel(result[0], result[1], service=self.service)
        self.log.add('genome_reconstruction',
                     prev,
                     self.recon_model,
                     context='reconstruct_genome')

    def label_reactions(self):
        """
    Labels morph's reactions from translated model, reconstruction, and source

    Populates the rxn_labels attribute in the Morph object with a Dictionary of four dictionaries of
    reaction_id -> value tuples.
    The first level dicts are named with the keys:
        - gene-match
        - gene-no-match
        - no-gene
        - recon
    Populates morph.probhash with a dictionary of compartment-truncated reaction_ids to their probability relative to
    genome in question (derived from morph.probanno).
    Also populates morph.objects, morph.info with data from KBase objects (advanced use)

    Technical Details (Consult if you are encountering issues):
    For simplicity, an end user can treat the interiors of each dictionary like a set of reaction ids, but it is
    important to note the this is actually a nested dictionary with entries of the form:
    reaction_id -> (model_index, probability)
    Thus, some set behavior works, but some doesn't, the user must account for the fact that these are dictionaries:

        >>>'rxn09073_c0' in morph.rxn_labels['gene-no-match']

            works and returns True or False, indicating whether or not rxn09073_c0 is a gene-no-match reaction

        >>>morph.rxn_labels['gene-match'].add('rxn00456_c0')

        fails and throws an exception. add() is a set method and can't be used on dictionaries. (You could set an
        entry with real or arbitrary value to get around this if you really wished)

    Each inner dictionary is keyed with reaction_ids, hashed to tuples as such: (model_index, probability)
    Where reaction_id is a kbase reaction id with the compartment info appended to the end (e.g. rxn01316_c0),
    model_index is the index of the reaction in the objects['x_model'][modelreactions] list, and the probability
    is the reaction probability associated with each reaction from the probanno object. Reactions not in ProbAnno
    are given an arbitrary probability of -1.0

    Example evaluations:
    >>>rxn_labels['gene-no-match']['rxn01316_c0'][0]
    evaluates to the index of rxn01316_c0 in morph.objects['trans_model']['modelreactions']
    >>>rxn_labels['gene-no-match']['rxn01316_c0'][1]
    evaluates to the reaction probability of rxn01316_c0
    >>>'rxn01316_c0' in rxn_labels['gene-no-match']
    will evaluate True if the reaction is a gene-no-match reaction (an inner dict key)

    Note
    ----
    Function Requirements:
        - morph.probanno is a ReactionProbabilities
        - morph.src_model, morph.recon_model, morph.trans_model are FBAModels
        - morph.ws_id is the ID of a readable/writeable service workspace


    Post-Condition
    -------
    Morph
        a morph in which morph.rxn_labels holds a dictionary with the keys 'gene-match', gene-no-match', 'recon'
        and 'no-gene'. The value of each key holds a dictionary with 0 or more entries of the form:
            reaction_id -> (model_index, probability)
        morph.probhash contains a dictionary of reaction_ids (COMPARTMENT TRUNCATED) mapped to their probabilities
            e.g. rxn09876 -> 0.04545339

    Examples
    --------
    Given a morph of the form (only relevant attributes shown):

    >>>morph = Client.label_reactions(morph)

    would produce something like:

        probannows: 9145
        ws_name: MMws235
        src_modelws: 9145
        src_model: 19
        trans_model: 3
        probhash: ['rxn05653', 'rxn12345', rxn59595', 'rxn45644' ... (more)]
        rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
        ws_id: 11444
        recon_model: 4
        probanno: 15
        morph.objects = ['source_model', 'recon_model', 'trans_model', 'probanno']
        morph.info = ['source_model', 'recon_model', 'trans_model', 'probanno']

    These could be examined like so:

    >>>morph.rxn_labels['no-gene'].keys()[1]
    u'rxn10316_c0'

    >>>morph.rxn_labels['no-gene']['rxn10316_c0'][1]
    0.444456666959

    >>>'rxn10316_c0' in morph.rxn_labels['no-gene']
    True
    """
        # get reaction sets
        recon_dict = dict([(r.rxn_id(), r)
                           for r in self.recon_model.get_reactions()])
        trans_dict = dict([(r.rxn_id(), r)
                           for r in self.trans_model.get_reactions()])
        model_dict = dict([(r.rxn_id(), r)
                           for r in self.src_model.get_reactions()])
        # create the rxn_labels dictionary
        self.rxn_labels = {
            'gene-no-match': dict(),
            'gene-match': dict(),
            'no-gene': dict(),
            'recon': dict(),
            'common': dict()
        }
        # Some reference sets
        all_reactions = set(model_dict.keys()).union(recon_dict.keys())
        for rxn in all_reactions:
            if rxn in trans_dict and rxn in recon_dict:
                self.rxn_labels['common'][rxn] = (trans_dict[rxn],
                                                  recon_dict[rxn])
            if rxn in model_dict and rxn not in trans_dict:
                if rxn not in recon_dict:
                    self.rxn_labels['gene-no-match'][rxn] = model_dict[rxn]
                else:
                    self.rxn_labels['recon'][rxn] = recon_dict[rxn]
            if rxn in trans_dict:
                gpr = trans_dict[rxn].gpr
                if gpr.gpr_type == 'no-gene' and rxn not in recon_dict:
                    self.rxn_labels['no-gene'][rxn] = trans_dict[rxn]
                else:
                    if rxn in recon_dict:
                        self.rxn_labels['gene-match'][rxn] = recon_dict[rxn]
                    else:
                        self.rxn_labels['gene-match'][rxn] = trans_dict[rxn]
            if rxn in recon_dict and rxn not in trans_dict and rxn not in model_dict:
                self.rxn_labels['recon'][rxn] = recon_dict[rxn]

    def build_supermodel(self):
        """
    Sets morph.model to a superset of all reactions in morph.rxn_labels

    Note
    ----
    Function Requirements:
        - morph.rxn_labels is a dictionary with the four keys ['gene-match', 'gene-no-match', 'recon', 'no-gene'],
        and it's values are dictionaries with entries of the form: reaction_id -> (model_index, probability)
        - morph.objects contains entries for the 'source_model' and 'recon_model' with data for the models in KBase (this
        is the output of the label_reactions(morph) function)

    Parameters
    ----------
    morph: Morph
        The morph for which you want to build a super_model (initializing morph.model)

    Returns
    -------
    Morph
        a morph object where morph.model, morph.ws_id forms a valid ObjectIdentity for a
        readable/writable KBase model object (the super-model)

    Examples
    --------
    Given a morph like so (only relevant attributes shown):

        ws_name: MMws235
        trans_model: 3
        rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
        ws_id: 11444
        morph.objects = ['source_model', 'recon_model', 'trans_model', 'probanno']
        morph.model = None

    >>>morph = Client.build_supermodel(morph)

    would produce something like this:

        ws_name: MMws235
        trans_model: 3
        rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
        ws_id: 11444
        morph.objects = ['source_model', 'recon_model', 'trans_model', 'probanno']
        morph.model = 5

    Where morph.model, morph.ws_id forms a valid ObjectIdentity for a model object in KBase (the super model)
    """
        if self.merge_conflicts is None:
            self.merge_conflicts = []
        src_rxns = dict([(r.rxn_id(), r)
                         for r in self.src_model.get_reactions()])
        super_rxns = dict()
        specials = list()
        # copy the trans model
        self.model = self.trans_model.copy(self.service,
                                           workspace_id=self.ws_id)
        #  ---->
        # Adding reactions into the translation.
        # First, go through every reaction they have in common and adjust if
        # necessary:
        reactions_to_remove = []
        adjustments = []
        for rxn_id in self.rxn_labels['common']:
            trans_rxn = self.rxn_labels['common'][rxn_id][0]  # MR
            recon_rxn = self.rxn_labels['common'][rxn_id][1]  # MR
            merge_gpr = trans_rxn.gpr.merge(recon_rxn.gpr)
            direction = _general_direction(trans_rxn, recon_rxn)
            if trans_rxn.gpr != merge_gpr or trans_rxn.get_direction(
            ) != direction:
                self.merge_conflicts.append(rxn_id)
                super_rxns[rxn_id] = recon_rxn
                adjustments.append(
                    (recon_rxn.get_removal_id(), direction, merge_gpr))
                removal_id = trans_rxn.get_removal_id()
                reactions_to_remove.append(removal_id)
        # ---->
        # removes the rxns we need to remove in place vs. making a new copy
        self.service.remove_reactions_in_place(self.model, reactions_to_remove)
        # Next, add all the reactions that aren't already in the translation:
        # Add the GENE_NO_MATCH reactions:
        for rxn_id in self.rxn_labels['gene-no-match']:
            reaction = self.rxn_labels['gene-no-match'][rxn_id]
            # need to remove gene references to avoid miscounting a gene that actually belongs to source organism
            reaction.data['modelReactionProteins'] = []
            if reaction.is_special_ref():
                specials.append(reaction)
            else:
                super_rxns[rxn_id] = reaction
        # Add the RECON reactions:
        for rxn_id in self.rxn_labels['recon']:
            reaction = self.rxn_labels['recon'][rxn_id]
            if rxn_id in src_rxns:
                direction = _general_direction(reaction, src_rxns[rxn_id])
            else:
                direction = reaction.get_direction()
            if reaction.is_special_ref():
                specials.append(reaction)
            else:
                if rxn_id not in super_rxns:
                    super_rxns[rxn_id] = reaction
                    adjustments.append(
                        (reaction.get_removal_id(), direction, reaction.gpr))

        # ---->
        result = self.service.add_reactions_manually(self.model,
                                                     super_rxns.values(),
                                                     name='super_model')
        self.model = FBAModel(result[0], result[1], service=self.service)
        self.service.adjust_directions_and_gprs(self.model, adjustments)
        result = self.service.add_reactions_manually(self.model,
                                                     specials,
                                                     name='super_modelspc')
        self.model = FBAModel(result[0], result[1], service=self.service)

    def prepare_supermodel(self, fill_src=False):
        """
        Composition of the first several steps in the algorithm

        1) Fill the source model to media using probabilistic gapfilling (can be skipped if fill_src keyword arg is set to False)
        2) Translate the src_model to a pouplate morph.trans_model
        3) Draft reconstruction of target genome fills morph.recon_model field
        4) label reactions in the morph (populates morph.rxn_labels)
        5) Builds a super_model and puts it in the morph.model field. The model is now ready for the process_reactions function

        Note
        ----
        Function Requirements:
            - morph.probanno, morph.probannows form a valid ObjectIdentity for a readable RxnProbs object in KBase
            - morph.src_model, morph.src_modelws form a valid ObjectIdentity for a readable model object in KBase
            - morph.media, morph.mediaws form a valid ObjectIdentity for a readable media object in KBase
            - morph.genome, morph.genomews form a valid ObjectIdentity for a readable genome object in KBase
            - morph.protcomp, morph.protcompws form a valid ObjectIdentity for a readable protein comparison object in KBase
            - morph.ws_id is the ID of a writeable KBase workspace

        Parameters
        ----------
        morph: Morph
            An initialized Morph with the following Requirements:
                - morph.ws_id is a valid KBase workspace_id that user has permission
                to write to
                - morph has valid object identities for src_model, genome, probanno,
                protcomp (These 4 are object_ids, their ___ws counterparts are workspace_ids
                of user readable workspaces)
        fill_src: boolean,optional
            a boolean indicating that the src_model should first be filled using probabilistic gapfilling
            Optional, default is true.

        Returns
        -------
        Morph
            A Morph with the following state changes:
                - morph.model has the object_id of the super_model in KBase
                - morph.rxn_labels has the labels for the reactions in the super
                model
                - morph.probhash has the probability hash for reactions related to
                Target genome
                - morph.trans_model has the object_id of the translated model
                - morph.recon model has the object_id of the reconstruction of
                Target Genome

        Examples
        --------
        Suppose you have a morph initialized like so: (this is the output of Helpers.make_morph() )

        >>> morph = make_morph()

            probannows: 9145
            ws_name: MMws235
            src_modelws: 9145
            protcompws: 9145
            src_model: 19
            media: 18
            removed_ids: None
            mediaws: 9145
            trans_model: None
            probhash: None
            genomews: 9145
            essential_ids: None
            genome: 3
            rxn_labels: None
            model: None
            ws_id: 11444
            recon_model: None
            probanno: 15
            protcomp: 6

        A call to Client.prepare_supermodel(morph) will return a morph of this sort of form:

        >>> morph = Client.prepare_supermodel(morph)

            probannows: 9145
            ws_name: MMws235
            src_modelws: 9145
            protcompws: 9145
            src_model: 19
            media: 18
            removed_ids: None
            mediaws: 9145
            trans_model: 3
            probhash: [u'rxn00001' ... u'rxn97854']
            genomews: 9145
            essential_ids: None
            genome: 3
            rxn_labels: ['gene-no-much', 'gene-match', 'recon', 'no-gene']
            model: 5
            ws_id: 11444
            recon_model: 4
            probanno: 15
            protcomp: 6

        See Also
        --------
        fill_src_to_media
        translate_features
        reconstruct_genome
        label_reactions
        build_supermodel

        This functions post condition preps the morph for the Client.process_reactions(morph) function
        """
        if fill_src:
            self.fill_src_to_media()
        self.translate_features()
        self.reconstruct_genome()
        self.label_reactions()
        self.build_supermodel()

    def process_reactions(self,
                          rxn_list=None,
                          name=None,
                          growth_condition=None,
                          num_reactions=-1):
        if growth_condition is None:
            growth_condition = GrowthConditions.SimpleCondition(
                service=self.service)
        """
        Attempts removal of rxn_list reactions from morph (i.e. morph.rxn_labels[label])

        Attempts removal of each reaction , keeping it only if it is essential to the objective function.
        Populates morph.essential_ids with the reaction_ids that could not be removed without breaking the model.
        morph.removed_ids is populated with the ids of the reactions that were removed. Both are populated as a dictionary of
        reaction_ids to their model_index and probability (like the entries in rxn_labels).
            e.g. reaction_id -> (model_index, probability)

        if rxn_list is None, the function removes (in low to high probability order) gene-no-match reactions followed by no-gene reactions

        Controlling name and process_count parameters allows the user tocontrol the number of models created in the morph.ws_id

        Note
        ----
        Function Requirements:
            - if rxn_list is None, rxn_labels['gene-no-match'] and rxn_labels['no-gene'] must be dictionaries
            with 0 or more entries of the form reaction_id -> (model_index, probability)
            - morph.model, morph.ws_id form a valid ObjectIdentity for a readable model object in KBase
            - morph.ws_id is the ID of a writeable KBase workspace

        Parameters
        ----------
        morph: Morph
            The morph containing the model (morph.model) from which reactions will be removed
        rxn_list: list, optional
            A sorted list of tuples of the form (reaction_id, (model_index, probability)) which will be processed from morph,model
            (form is the output of removal_list() function)
            (if left out, all gene-no-match follwed by all no-gene reactions will be processed in low to high likelihood order)
        name: String, optional
            Setting name will begin all output model names with name. Default is MM
            output models are named as follows: str(name) + '-' + str(process_count)
        process_count: int, optional
            A number indicating how many reactions have been processed so far, used in nameing output models. Default is 0.
            output models are named as follows: str(name) + '-' + str(process_count)
        get_count: Boolean, optional
            A Boolean flag indicating whether the process_count should be returned with the morph (as a tuple). Used when not processing all
            reactions at once. Deafault is False

        Returns
        -------
        Morph
            A morph with a new model, and essential_ids/removed)ids used to keep track of changes
        int (Only if get_count=True)
            process_count (number of models created, used for name managing)

        Examples
        --------
        Given a morph of the form (only relevant attributes shown):
            ws_name: MMws235
            rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
            ws_id: 11444
            morph.model = 5
            morph.essential_ids = None
            morph.removed_ids = None

        >>>morph = Client.process_reactions(morph, rxn_list=Client.removal_list(morph.rxn_labels['gene-no-match'], list_range=(0, 10)))

        would process the 10 least likely gene-no-match reactions, which might produce a morph like this:

            ws_name: MMws235
            rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
            ws_id: 11444
            morph.model = 5
            morph.essential_ids = ['rxn10316_c0', 'rxn23434_c0', 'rxn78687_c0']
            morph.removed_ids = ['rxn11123_c0', 'rxn34534_c0', 'rxn90565_c0', 'rxn78987_c0', 'rxn12321_c0', 'rxn89034_c0', 'rxn88888_c0']

        where removal of one of the reactions given by a key in morph.essential_ids would result in a model that has an objective value of 0.000 in FBA simulation

        :param get_count:
        :param process_count:
        :param name:
        :param rxn_list:
        :param iterative_models:
        :param growth_condition:
        """
        ws = self.ws_id

        # Sort by probanno. items() returns (K, V=(model_index, prob))

        def get_key(item):
            return self.get_prob(item[0])

        # label argument behavior
        if rxn_list is None:
            rxn_dict = self.rxn_labels['gene-no-match']
            removal_list = sorted(rxn_dict.items(), key=get_key)
            rxn_dict = self.rxn_labels['no-gene']
            removal_list += sorted(rxn_dict.items(), key=get_key)
            removal_list = [
                r for r in removal_list
                if r[0] not in self.rxn_labels['common']
            ]
        else:
            removal_list = rxn_list
        # instantiate lists only if needed
        if self.essential_ids is None:
            self.essential_ids = dict()
        if self.removed_ids is None:
            self.removed_ids = dict()
        # Give objs a general name if none is provided
        if name is None:
            name = 'MorphedModel'
        max = num_reactions >= 0 and num_reactions or len(removal_list)
        for i in range(max):
            removal_id = removal_list[i][1].get_removal_id()
            rxn = removal_list[i][0]
            if removal_id.startswith('rxn00000'):
                self.log.add('skip', [self.model, removal_list[i][1]], [None],
                             context='process_reactions')
                continue
            print '\nReaction to remove: ' + str(removal_id) + " / " + str(rxn)
            # TODO Find someway to fix the behavior bug if model_id is not in ws, etc.
            info = self.service.remove_reaction(self.model,
                                                removal_id,
                                                output_id='morph_candidate')
            candidate_model = FBAModel(info[0], info[1], service=self.service)
            if growth_condition.evaluate({
                    'morph': self,
                    'model': candidate_model
            }):
                # removed successfully
                self.log.add('Removed Reaction',
                             [self.model, growth_condition.fba],
                             [candidate_model],
                             context='process reactions')
                # overwrite current morph with candidate
                info = self.service.copy_object(
                    (candidate_model.object_id, candidate_model.workspace_id),
                    (name, self.model.workspace_id))
                self.model = FBAModel(info[0], info[1], service=self.service)
                self.removed_ids[removal_id] = removal_list[i][1]
            else:
                # essential
                self.log.add('Kept Reaction',
                             [self.model, growth_condition.fba],
                             [candidate_model],
                             context='process reactions')
                self.essential_ids[removal_id] = removal_list[i][1]
            print self.log.actions[-1].type + ' ' + str(
                removal_id) + ', FBA was ' + str(
                    growth_condition.fba.objective)
        return self

    def get_prob(self, rxn_id):
        '''
        returns the probanno likelihood for a reaction in a morph
        '''
        #TODO: Will Users ever have their own probannos? YES
        if self.probanno is None:
            # This means probabilistic annotations are not required, but used if present
            return -1.0
        if self.probhash is None:
            self.probhash = self.probanno.probability_hash()
        try:
            result = self.probhash[rxn_id.split('_')[0]]
        except KeyError:
            result = -1.0
        return result

    def translate_media(self, new_media):
        """
        transfers a growing model to a new media and ensures growth in this media, gpafilling if necessary
        """
        self.media = new_media
        if not self.runfba().objective > 0:
            prev_rxns = set(([r.rxn_id() for r in self.model.get_reactions()]))
            info = self.service.gapfill_model(self.model,
                                              self.media,
                                              workspace=self.ws_id)
            filled_model = FBAModel(info[0], info[1], service=self.service)
            filled_rxns = dict([(r.rxn_id(), r)
                                for r in filled_model.get_reactions()])
            new_reactions = set(filled_rxns.keys()) - prev_rxns
            for r in new_reactions:
                self.rxn_labels['no-gene'][r] = filled_rxns[r]
            # KBASE QUIRKS MAKE THIS LINE THE OPPOSITE OF WHAT WE WANT:
            self.model = filled_model
            assert self.runfba().objective > 0

    def get_labels(self, reaction_ids):
        """
        Given a set of reaction_ids, return the labels for the reactions

        :param reaction_ids: list<str> of reaction ids. e.g. 'rxn12345_c0'
        :return: dict<str, list<str>> of ids to list of labels
        """

        result = dict()
        for r in reaction_ids:
            result[r] = []
            for label in self.rxn_labels:
                if r in self.rxn_labels[label]:
                    result[r].append(label)
        return result
Пример #11
0
class DCGame(Model):
    def __init__(self, adjMat, numVisibleColorNodes, numAdversarialNodes,
                 inertia):
        self.adjMat = adjMat
        self.numVisibleColorNodes = numVisibleColorNodes
        self.numAdversarialNodes = numAdversarialNodes
        # self.adversarialNodes = []
        self.visibleColorNodes = []
        self.regularNodes = []
        self.schedule = RandomActivation(self)
        self.numAgents = len(adjMat)
        self.inertia = inertia
        # if there are 20 consensus colors then a
        # terminal state is reached
        self.terminate = False
        self.time = 0
        # logging information
        self.log = Log()

        ##  temporarily added this for figuring out
        ##  why visible nodes have no help
        self.hasConflict = False

        # convert adjMat to adjList
        def getAdjList(adjMat):
            adjList = {key: [] for key in range(self.numAgents)}
            for node in range(self.numAgents):
                adjList[node] = [
                    idx for idx, value in enumerate(adjMat[node])
                    if value == True
                ]
            return adjList

        self.adjList = getAdjList(self.adjMat)

        ############# designate adversarial #############
        # (node, degree)
        node_deg = [(idx, count(adjMat[idx])) for idx in range(self.numAgents)]
        # select the top-k nodes with largest degrees as adversarial
        node_deg.sort(key=lambda x: x[1], reverse=True)
        self.adversarialNodes = [
            item[0] for item in node_deg[:self.numAdversarialNodes]
        ]

        ############# designate visible nodes #############
        availableNodes = shuffled(node_deg[self.numAdversarialNodes:])
        self.visibleColorNodes = [
            item[0] for item in availableNodes[:self.numVisibleColorNodes]
        ]

        self.regularNodes = [
            n for n in range(self.numAgents) if n not in self.adversarialNodes
        ]
        # make sure we have 20 regular nodes
        assert len(self.regularNodes) == 20

        # adversarial nodes and regular nodes should not overlap
        assert set(self.adversarialNodes) & set(self.regularNodes) == set()
        # visible nodes should belong to regular nodes
        assert set(self.visibleColorNodes) & set(self.regularNodes) == set(
            self.visibleColorNodes)

        # logging simulation configuration
        self.log.add("#visible nodes: " + str(self.visibleColorNodes))
        self.log.add("#adversarial nodes: " + str(self.adversarialNodes))
        self.log.add("#regular nodes: " + str(self.regularNodes) + '\n')

        ############# initialize all agents #############
        for i in range(self.numAgents):
            # if i is a visible node
            isVisibleNode = i in self.visibleColorNodes
            # if i is an adversarial
            isAdversarial = i in self.adversarialNodes
            # make sure adversarial nodes are not intersected with visible nodes
            assert isVisibleNode & isAdversarial == False

            neighbors = self.adjList[i]

            # visible color nodes in i's neighbors
            vNode = list(set(neighbors) & set(self.visibleColorNodes))
            # if i == 6:
            #     print(vNode)
            inertia = self.inertia

            # print("Add agent:", (i, visibleNode, adversarial, neighbors, visibleColorNodes))
            a = GameAgent(i, isVisibleNode, isAdversarial, neighbors, vNode,
                          inertia, self)
            self.schedule.add(a)

        # instantiate all nodes' neighbors and visibleColorNodes
        for agent in self.schedule.agents:
            agent.instantiateNeighbors(self)
            agent.instantiateVisibleColorNodes(self)

        self.datacollector = DataCollector(
            model_reporters={
                "red": getRed,
                "green": getGreen
            },
            agent_reporters={"agent_color": lambda a: a.color})

    # simulate the whole model for one step
    def step(self):
        # # # if either red or green reaches consensus, terminates!
        # # in terminal state we do not collect data
        if not self.terminate:
            self.datacollector.collect(self)
            self.schedule.step()
        return self.terminate

    def simulate(self, simulationTimes):
        for i in range(simulationTimes):
            # update model's time
            self.updateTime(i)
            terminate = self.step()
            if terminate:
                break
        # output log file to disk
        self.log.outputLog('result/simResult.txt')
        simulatedResult = self.datacollector.get_model_vars_dataframe()
        return simulatedResult

    # update model's clock
    def updateTime(self, t):
        self.time = t

    def setTerminal(self):
        assert self.terminate == False
        self.terminate = True

    def addRecord(self, msg):
        self.log.add(msg)

    # for degub purpose only
    def outputAdjMat(self, path):
        with open(path, 'w') as fid:
            for line in self.adjMat:
                # convert list of boolean values to string values
                tline = ["1" if item else "0" for item in line]
                fid.write(' '.join(tline) + '\n')
Пример #12
0
class DCGame(Model):
    def __init__(self, adjMat, G, numVisibleColorNodes, numAdversarialNodes,
                 inertia, beta, delay, visibles, adversaries):
        self.adjMat = adjMat
        self.numVisibleColorNodes = numVisibleColorNodes
        self.numAdversarialNodes = numAdversarialNodes
        # self.adversarialNodes = []
        self.visibleColorNodes = []
        self.regularNodes = []
        self.schedule = FollowVisibleActivation(self)
        self.numAgents = len(adjMat)
        self.inertia = inertia
        # if there are 20 consensus colors then a
        # terminal state is reached
        self.terminate = False
        self.time = 0
        # logging information
        self.log = Log()

        ##  temporarily added this for figuring out
        ##  why visible nodes have no help
        self.hasConflict = False

        # randomize regular players (exclude visibles)
        # decision
        self.beta = beta

        # a amount of time to delay ordinary players' decision
        # ordinary players = players who are neither visibles
        # nor has any visibles in their neighbor
        self.delay = delay

        # total number of color changes in a game
        self.colorChanges = 0

        # addded by Yifan
        self.reach_of_adversaries = 0
        self.reach_of_visibles = 0
        self.total_cnt_of_adversaries = 0
        self.total_cnt_of_visibles = 0
        self.graph = G

        # convert adjMat to adjList
        def getAdjList(adjMat):
            adjList = {key: [] for key in range(self.numAgents)}
            for node in range(self.numAgents):
                #adjList[node] = [idx for idx, value in enumerate(adjMat[node]) if value == True]
                adjList[node] = [
                    idx for idx, value in enumerate(adjMat[node])
                    if value == 'True'
                ]
            return adjList

        self.adjList = getAdjList(self.adjMat)

        #return the subset of L availableNodes in G with the largest number of distinct neighbors
        def getSubsetWithMaxDistinctNeighbors(availableNodes, G, L):
            acc = []
            max_cnt = 0
            local_cnt = 0
            hasBeenConsidered = [False for i in range(self.numAgents)]
            graph = nx.convert.to_dict_of_lists(G)
            for subset in itertools.combinations(availableNodes, L):
                upper_bound = 0
                for agent in subset:
                    upper_bound += len(graph[agent])
                if upper_bound < max_cnt:
                    continue
                # compute reach
                for agent in subset:
                    for neighbor in G.neighbors(agent):
                        if neighbor not in subset and hasBeenConsidered[
                                neighbor] == False:
                            local_cnt += 1
                            hasBeenConsidered[neighbor] = True
                if local_cnt > max_cnt:
                    max_cnt = local_cnt
                    acc.clear()
                    for agent in subset:
                        acc.append(agent)
                local_cnt = 0
                hasBeenConsidered = [False for i in range(self.numAgents)]
            return acc

        ############# designate visible #############
        # node_deg = [(idx, count(adjMat[idx])) for idx in range(self.numAgents)]
        # availableNodes = [item[0] for item in node_deg]
        # random.shuffle(availableNodes)
        # availableNodes.sort(key=lambda x : x)
        # self.visibleColorNodes = getSubsetWithMaxDistinctNeighbors(availableNodes, G, numVisibleColorNodes)
        # self.visibleColorNodes = [item for item in availableNodes[:self.numVisibleColorNodes]]
        self.visibleColorNodes = visibles
        # for visibleNode in self.visibleColorNodes:
        #     availableNodes.remove(visibleNode)

        ############# designate adversarial ###############
        # self.adversarialNodes = getSubsetWithMaxDistinctNeighbors(availableNodes, G, numAdversarialNodes)
        # self.adversarialNodes = [item for item in availableNodes[:self.numAdversarialNodes]]
        self.adversarialNodes = adversaries

        # ================ prev version: designate adversarial and visible nodes ===========
        # node_deg = [(idx, count(adjMat[idx])) for idx in range(self.numAgents)]
        # all_nodes = [item[0] for item in node_deg]
        # random.shuffle(node_deg)
        # self.adversarialNodes = [item[0] for item in node_deg[:self.numAdversarialNodes]]

        # reach_of_adversaries = 0
        # total_cnt_of_adversaries = 0
        # hasBeenReached = dict.fromkeys(all_nodes, False)
        # for adversarialNode in self.adversarialNodes:
        #     for neighbor in G.neighbors(adversarialNode):
        #         if neighbor not in self.adversarialNodes:
        #             total_cnt_of_adversaries += 1
        #         if neighbor not in self.adversarialNodes and hasBeenReached[neighbor] == False:
        #             reach_of_adversaries += 1
        #             hasBeenReached[neighbor] = True
        # self.reach_of_adversaries = reach_of_adversaries
        # self.total_cnt_of_adversaries = total_cnt_of_adversaries

        # ############# designate visible nodes #############
        # availableNodes = shuffled(node_deg[self.numAdversarialNodes:])
        # self.visibleColorNodes = [item[0] for item in availableNodes[:self.numVisibleColorNodes]]

        # reach_of_visibles = 0
        # total_cnt_of_visibles = 0
        # hasBeenReached = dict.fromkeys(all_nodes, False)
        # for visibleColorNode in self.visibleColorNodes:
        #     for neighbor in G.neighbors(visibleColorNode):
        #         if neighbor not in self.adversarialNodes and neighbor not in self.visibleColorNodes:
        #             total_cnt_of_visibles += 1
        #         if neighbor not in self.adversarialNodes and neighbor not in self.visibleColorNodes and hasBeenReached[neighbor] == False:
        #             reach_of_visibles += 1
        #             hasBeenReached[neighbor] = True
        # self.reach_of_visibles = reach_of_visibles
        # self.total_cnt_of_visibles = total_cnt_of_visibles

        # ===============================

        self.regularNodes = [
            n for n in range(self.numAgents) if n not in self.adversarialNodes
        ]
        # make sure we have 20 regular nodes
        # assert len(self.regularNodes) ==20

        assert set(self.adversarialNodes) & set(
            self.visibleColorNodes) == set()
        # adversarial nodes and regular nodes should not overlap
        assert set(self.adversarialNodes) & set(self.regularNodes) == set()
        # visible nodes should belong to regular nodes
        assert set(self.visibleColorNodes) & set(self.regularNodes) == set(
            self.visibleColorNodes)

        # logging simulation configuration
        self.log.add("#visible nodes: " + str(self.visibleColorNodes))
        self.log.add("#adversarial nodes: " + str(self.adversarialNodes))
        self.log.add("#regular nodes: " + str(self.regularNodes) + '\n')

        ############# initialize all agents #############
        for i in range(self.numAgents):
            # if i is a visible node
            isVisibleNode = i in self.visibleColorNodes
            # if i is an adversarial
            isAdversarial = i in self.adversarialNodes
            # make sure adversarial nodes are not intersected with visible nodes
            assert isVisibleNode & isAdversarial == False

            neighbors = self.adjList[i]

            # visible color nodes in i's neighbors
            vNode = list(set(neighbors) & set(self.visibleColorNodes))

            inertia = self.inertia
            beta = self.beta

            # print("Add agent:", (i, visibleNode, adversarial, neighbors, visibleColorNodes))
            a = GameAgent(i, isVisibleNode, isAdversarial, neighbors, vNode,
                          inertia, beta, self)
            self.schedule.add(a)

        # instantiate all nodes' neighbors and visibleColorNodes
        for agent in self.schedule.agents:
            agent.instantiateNeighbors(self)
            agent.instantiateVisibleColorNodes(self)

        self.datacollector = DataCollector(
            model_reporters={
                "red": getRed,
                "green": getGreen
            },
            agent_reporters={"agent_color": lambda a: a.color})

    def getReachOfAdversaries(self):
        return self.reach_of_adversaries

    def getReachOfVisibles(self):
        return self.reach_of_visibles

    def getTotalCntOfAdversaries(self):
        return self.total_cnt_of_adversaries

    def getTotalCntOfVisibles(self):
        return self.total_cnt_of_visibles

    # simulate the whole model for one step
    def step(self):
        # # # if either red or green reaches consensus, terminates!
        # # in terminal state we do not collect data
        if not self.terminate:
            self.datacollector.collect(self)
            self.schedule.step(self.delay)
        return self.terminate

    def simulate(self, simulationTimes):
        for i in range(simulationTimes):
            # update model's time
            # print("simulation time: " + str(i))
            self.updateTime(i)
            terminate = self.step()
            if terminate:
                break

        #added by Yifan
        isRegWhite = False
        # output log file to disk
        if not terminate:
            # did not reach consensus
            for agent in self.schedule.agents:
                if not agent.isAdversarial and not agent.isVisibleNode and agent.color == "white":
                    #at least one regular player remained white
                    isRegWhite = True

        self.log.outputLog('result/simResult.txt')
        simulatedResult = self.datacollector.get_model_vars_dataframe()
        # print(simulatedResult)
        return (simulatedResult, isRegWhite)

    # update model's clock
    def updateTime(self, t):
        self.time = t

    def setTerminal(self):
        assert self.terminate == False
        self.terminate = True

    def addRecord(self, msg):
        self.log.add(msg)

    # for degub purpose only
    def outputAdjMat(self, path):
        with open(path, 'w') as fid:
            for line in self.adjMat:
                # convert list of boolean values to string values
                tline = ["1" if item else "0" for item in line]
                fid.write(' '.join(tline) + '\n')
Пример #13
0
class Logic:
    """Logic module for StarChart. Contains all methods called by main.py.
    
    Class variables:
        lock    -- Holds the coordinates of the locked object, False if nothing is locked
        state   -- Holds the screen UI is currently in
    """

    #Initializing
    #TODO: make config file specific to plotter (config_plot.ini)
    #TODO: review previous todo
    #TODO: implement turns and orbits around planets when turns pass

    #states = main, terrain, battle, tech, etc..
    state = State_Main
    state_chain = [state]
    Plot.start()
    Board.start(5)
    State_Main.init()
    Log.add("Program started")

    @classmethod
    def update_screen_size(cls):
        """ Updates values of width and height of the screen (x,y) in plotter.
        
        If the terminal's size has changed, updates size values in the plotter"""

        #TODO: mobve to  plotter
        y, x = Plot.scr.getmaxyx()
        if (Plot.y != y or Plot.x != x):
            Plot.y, Plot.x = Plot.scr.getmaxyx()
            Plot.y -= 1

    @classmethod
    def refresh(cls):
        """Clears screen to draw next frame."""
        #TODO: move to  plotter

        Logic.update_screen_size()
        Plot.scr.refresh()
        Plot.scr.clear()

    @classmethod
    def draw_state(cls):
        """Calls various methods in plotter module to draw the board and UI elements."""
        #TODO: this method became superflous
        cls.state.plot()

    @classmethod
    def handle_lock(cls):
        locked = Board.terrain[Logic.lock[0]][Logic.lock[1]]
        if "Ship" in locked.identity:
            Plot.draw_lock(Board.terrain[Logic.lock[0]][Logic.lock[1]],
                           Logic.lock[0], Logic.lock[1])
        """
        elif locked.search() == "Planet":
            Plot.draw_terrain(locked)
        """

    @classmethod
    def get_input(cls):
        """Reads keyboard input from user"""
        return Plot.scr.getkey()

    @classmethod
    def handle_input(cls):
        """Takes the key pressed by the user and calls the appropiate method.
        
        Bindings:
            q       -- Quits game / Quits Menu
            w,a,s,d -- Moves cursor / UI Selection
            e       -- locks and unlocks cursor / Accept
            t y u
            g h j
            b n m
        """
        #change will be False if there is no need to change stage
        #if there is, change[0] will contain a string indicating either the stage
        #or an instruction for moving in the stage chain (like "back")
        #further indexes will contain the necessary arguments for the transition, like the object

        key = cls.get_input()

        change = cls.state.handle_input(key)
        if change:
            if change[0] == "end":
                cls.end()

            elif change[0] == "terrain":
                cls.state = State_Terrain
                cls.state_chain.append(cls.state)
                cls.state.init(change[1])

            elif change[0] in ["Minerals", "Humidity", "Elevation", "Info"]:
                cls.state = State_Terrain
                cls.state_chain[-1] = cls.state
                cls.state.change_view(change[0])

            elif change[0] in ["Build", "Select", "Remove"]:
                cls.state.change_action(change[0])

            elif change[0] == "back":
                cls.state_chain = cls.state_chain[:-1]
                cls.state = cls.state_chain[-1]

            elif change[0] == "main":
                cls.state_chain = cls.state_chain[0]
                cls.state = cls.state_chain[0]

            Log.add(str(cls.state_chain))

    @classmethod
    def end(cls, exception=''):
        """Calls method to perform necessary steps for clean exit."""
        Plot.end()
        if exception:
            Log.add(str(exception))
        Log.add('Exiting program')
        Log.print()
        exit()
Пример #14
0
class Morph:
    # These are the allowed properties of a morph object. Values not specified
    # by user are set to None
    # This is an Abstract Object representing the Morph of a metabolic model
    # from one species to a close relative genome. It has information related to
    # the source model, the target genome, the reactions in the model as it is
    # morphed from source import to target, and the set of
    properties = {'src_model', 'genome', 'probanno', 'protcomp', 'model', 'rxn_labels', 'ws_id', 'ws_name',
                  'trans_model',
                  'recon_model', 'media', 'probhash', 'log'}

    def __init__(self, *arg_hash, **kwargs):
        """
        Initiializes a Morph! A reasonable Morph needs each of the following set:
            src_model: (FBAModel) the model of the source organism
            genome: (Genome) the genome of the target organism
            probanno: (ReactionProbabilities) the likelihoods for KBase reactions in the target organism
            protcomp: (ProteomeComparison) the proteome comparison between source and target genomes
            media: (Media) the media for the source model and subsequent models
        :param arg_hash: a dictionary with the attributes desired as keys
        :param kwargs: keyword arguments
        :return:
        """
        # TODO: EDIT THIS DOC LINE WITH THE TRUTH
        self.src_model = None
        self.model = None
        self.genome = None
        self.probanno = None
        self.protcomp = None
        self.model = None
        self.rxn_labels = None
        self.media = None
        self.recon_model = None
        self.trans_model = None
        self.probhash = None
        self.log = None
        self.ws_id = None
        self.ws_name = None
        self.essential_ids = None
        self.removed_ids = None

        for dictionary in arg_hash:
            for key in dictionary:
                if key in Morph.properties:
                    setattr(self, key, dictionary[key])
        for key in kwargs:
            if key in Morph.properties:
                setattr(self, key, kwargs[key])
        for prop in Morph.properties:
            if not hasattr(self, prop):
                setattr(self, prop, None)
        if self.log is None:
            self.log = Log(self)
        if self.ws_id is None:
            self.ws_id, self.ws_name = service.init_workspace()
        self._check_rep()

    def _check_rep(self):
        if self.model is not None:
            assert isinstance(self.model, FBAModel), str(type(self.model))
        if self.src_model is not None:
            assert isinstance(self.src_model, FBAModel), str(type(self.src_model))
        if self.genome is not None:
            assert isinstance(self.genome, Genome), str(type(self.genome))
        if self.media is not None:
            assert isinstance(self.media, Media), str(type(self.media))
        if self.probanno is not None:
            assert isinstance(self.probanno, ReactionProbabilities), str(type(self.probanno))
        if self.protcomp is not None:
            assert isinstance(self.protcomp, ProteomeComparison), str(type(self.protcomp))
        if self.trans_model is not None:
            assert isinstance(self.trans_model, FBAModel), str(type(self.trans_model))
        if self.recon_model is not None:
            assert isinstance(self.recon_model, FBAModel), str(type(self.recon_model))

    def to_json(self):
        return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True)

    # Overridden Functions to produce unique output
    def __str__(self):
        output = ''
        for key in vars(self):
            attr = getattr(self, key)
            if isinstance(attr, dict):
                attr = attr.keys()
                if len(attr) < 100:
                    output += str(key) + ': ' + str(attr) + '\n'
                else:
                    output += str(key) + ': ' + str(attr[0:100]) + ' ... (more)\n'
            else:
                output += str(key) + ': ' + str(attr) + '\n'
        return output

    def __repr__(self):
        return str(self)

    def __unicode__(self):
        return unicode(str(self))

    def fill_src_to_media(self):
        """
        Gap-fills the Morphs source model to the provided media
        :return: None
        """
        prev = FBAModel(self.src_model.object_id, self.src_model.workspace_id)
        self.src_model = self.src_model.copy(workspace_id=self.ws_id)
        result = service.gapfill_model(self.src_model, self.media,
                                       workspace=self.ws_id, rxn_probs=self.probanno)
        self.src_model = FBAModel(result[0], result[1])
        self.log.add('gapfill', prev, self.src_model, context='fill_src_to_media')

    def runfba(self, model=None, media=None):
        """
        Run FBA on the model in the Morph
        :param model: (optional) FBAModel, default is morph.model
        :param media: (optional) Media, default is morph.media
        :return: FBA
        """
        if model is None:
            model = self.model
        if media is None:
            media = self.media
        objid, wsid = service.runfba(model, media, self.ws_id)
        return FBA(objid, wsid)

    def translate_features(self):
        """
        Translate morph.model using ProteomeComparison (morph.procomp) to a translated model
        :return: None (sets morph.trans_model)
        """
        prev = copy.deepcopy(self.trans_model)
        result = service.translate_model(self.src_model, self.protcomp, workspace=self.ws_id)
        self.trans_model = FBAModel(result[0], result[1])
        self.log.add('model_translation', prev, self.trans_model, context='translate_features')

    def reconstruct_genome(self):
        """
        Reconstruct the genome using automated reconstruction in the service form morph.genome
        :return: None (sets morph.recon_model)
        """
        prev = copy.deepcopy(self.recon_model)
        result = service.reconstruct_genome(self.genome, workspace=self.ws_id)
        self.recon_model = FBAModel(result[0], result[1])
        self.log.add('genome_reconstruction', prev, self.recon_model, context='reconstruct_genome')

    def label_reactions(self):
        """
    Labels morph's reactions from translated model, reconstruction, and source

    Populates the rxn_labels attribute in the Morph object with a Dictionary of four dictionaries of
    reaction_id -> value tuples.
    The first level dicts are named with the keys:
        - gene-match
        - gene-no-match
        - no-gene
        - recon
    Populates morph.probhash with a dictionary of compartment-truncated reaction_ids to their probability relative to
    genome in question (derived from morph.probanno).
    Also populates morph.objects, morph.info with data from KBase objects (advanced use)

    Technical Details (Consult if you are encountering issues):
    For simplicity, an end user can treat the interiors of each dictionary like a set of reaction ids, but it is
    important to note the this is actually a nested dictionary with entries of the form:
    reaction_id -> (model_index, probability)
    Thus, some set behavior works, but some doesn't, the user must account for the fact that these are dictionaries:

        >>>'rxn09073_c0' in morph.rxn_labels['gene-no-match']

            works and returns True or False, indicating whether or not rxn09073_c0 is a gene-no-match reaction

        >>>morph.rxn_labels['gene-match'].add('rxn00456_c0')

        fails and throws an exception. add() is a set method and can't be used on dictionaries. (You could set an
        entry with real or arbitrary value to get around this if you really wished)

    Each inner dictionary is keyed with reaction_ids, hashed to tuples as such: (model_index, probability)
    Where reaction_id is a kbase reaction id with the compartment info appended to the end (e.g. rxn01316_c0),
    model_index is the index of the reaction in the objects['x_model'][modelreactions] list, and the probability
    is the reaction probability associated with each reaction from the probanno object. Reactions not in ProbAnno
    are given an arbitrary probability of -1.0

    Example evaluations:
    >>>rxn_labels['gene-no-match']['rxn01316_c0'][0]
    evaluates to the index of rxn01316_c0 in morph.objects['trans_model']['modelreactions']
    >>>rxn_labels['gene-no-match']['rxn01316_c0'][1]
    evaluates to the reaction probability of rxn01316_c0
    >>>'rxn01316_c0' in rxn_labels['gene-no-match']
    will evaluate True if the reaction is a gene-no-match reaction (an inner dict key)

    Note
    ----
    Function Requirements:
        - morph.probanno is a ReactionProbabilities
        - morph.src_model, morph.recon_model, morph.trans_model are FBAModels
        - morph.ws_id is the ID of a readable/writeable service workspace


    Post-Condition
    -------
    Morph
        a morph in which morph.rxn_labels holds a dictionary with the keys 'gene-match', gene-no-match', 'recon'
        and 'no-gene'. The value of each key holds a dictionary with 0 or more entries of the form:
            reaction_id -> (model_index, probability)
        morph.probhash contains a dictionary of reaction_ids (COMPARTMENT TRUNCATED) mapped to their probabilities
            e.g. rxn09876 -> 0.04545339

    Examples
    --------
    Given a morph of the form (only relevant attributes shown):

    >>>morph = Client.label_reactions(morph)

    would produce something like:

        probannows: 9145
        ws_name: MMws235
        src_modelws: 9145
        src_model: 19
        trans_model: 3
        probhash: ['rxn05653', 'rxn12345', rxn59595', 'rxn45644' ... (more)]
        rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
        ws_id: 11444
        recon_model: 4
        probanno: 15
        morph.objects = ['source_model', 'recon_model', 'trans_model', 'probanno']
        morph.info = ['source_model', 'recon_model', 'trans_model', 'probanno']

    These could be examined like so:

    >>>morph.rxn_labels['no-gene'].keys()[1]
    u'rxn10316_c0'

    >>>morph.rxn_labels['no-gene']['rxn10316_c0'][1]
    0.444456666959

    >>>'rxn10316_c0' in morph.rxn_labels['no-gene']
    True
    """
        # get reaction sets
        recon_dict = dict([(r.rxn_id(), r) for r in self.recon_model.get_reactions()])
        trans_dict = dict([(r.rxn_id(), r) for r in self.trans_model.get_reactions()])
        model_dict = dict([(r.rxn_id(), r) for r in self.src_model.get_reactions()])
        # create the rxn_labels dictionary
        self.rxn_labels = {'gene-no-match': dict(),
                           'gene-match': dict(),
                           'no-gene': dict(),
                           'recon': dict(),
                           'common': dict()}
        # Some reference sets
        all_reactions = set(model_dict.keys()).union(recon_dict.keys())  # TODO: runtime will make you cry
        for rxn in all_reactions:
            if rxn in trans_dict and rxn in recon_dict:
                self.rxn_labels['common'][rxn] = (trans_dict[rxn], recon_dict[rxn])
            if rxn in model_dict and rxn not in trans_dict:
                if rxn not in recon_dict:
                    self.rxn_labels['gene-no-match'][rxn] = model_dict[rxn]
                else:
                    self.rxn_labels['recon'][rxn] = recon_dict[rxn]
            if rxn in trans_dict:
                gpr = trans_dict[rxn].gpr
                if gpr.gpr_type == 'no-gene' and rxn not in recon_dict:
                    self.rxn_labels['no-gene'][rxn] = trans_dict[rxn]
                else:
                    if rxn in recon_dict:
                        self.rxn_labels['gene-match'][rxn] = recon_dict[rxn]
                    else:
                        self.rxn_labels['gene-match'][rxn] = trans_dict[rxn]
            if rxn in recon_dict and rxn not in trans_dict and rxn not in model_dict:
                self.rxn_labels['recon'][rxn] = recon_dict[rxn]

    def build_supermodel(self):
        """
    Sets morph.model to a superset of all reactions in morph.rxn_labels

    Note
    ----
    Function Requirements:
        - morph.rxn_labels is a dictionary with the four keys ['gene-match', 'gene-no-match', 'recon', 'no-gene'],
        and it's values are dictionaries with entries of the form: reaction_id -> (model_index, probability)
        - morph.objects contains entries for the 'source_model' and 'recon_model' with data for the models in KBase (this
        is the output of the label_reactions(morph) function)

    Parameters
    ----------
    morph: Morph
        The morph for which you want to build a super_model (initializing morph.model)

    Returns
    -------
    Morph
        a morph object where morph.model, morph.ws_id forms a valid ObjectIdentity for a
        readable/writable KBase model object (the super-model)

    Examples
    --------
    Given a morph like so (only relevant attributes shown):

        ws_name: MMws235
        trans_model: 3
        rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
        ws_id: 11444
        morph.objects = ['source_model', 'recon_model', 'trans_model', 'probanno']
        morph.model = None

    >>>morph = Client.build_supermodel(morph)

    would produce something like this:

        ws_name: MMws235
        trans_model: 3
        rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
        ws_id: 11444
        morph.objects = ['source_model', 'recon_model', 'trans_model', 'probanno']
        morph.model = 5

    Where morph.model, morph.ws_id forms a valid ObjectIdentity for a model object in KBase (the super model)
    """
        src_rxns = dict([(r.rxn_id(), r) for r in self.src_model.get_reactions()])
        super_rxns = dict()
        specials = list()
        # copy the trans model
        self.model = self.trans_model.copy()
        #  ---->
        # Adding reactions into the translation.
        # First, go through every reaction they have in common and adjust if
        # necessary:
        reactions_to_remove = []
        for rxn_id in self.rxn_labels['common']:
            trans_rxn = self.rxn_labels['common'][rxn_id][0]  # MR
            recon_rxn = self.rxn_labels['common'][rxn_id][1]  # MR
            merge_gpr = trans_rxn.gpr.merge(recon_rxn.gpr)
            direction = _general_direction(trans_rxn, recon_rxn)
            if trans_rxn.gpr != merge_gpr or trans_rxn.get_direction() != direction:
                super_rxns[rxn_id] = (recon_rxn.get_rxn_ref(), recon_rxn.get_comp_ref(), direction, str(merge_gpr))
                removal_id = trans_rxn.get_removal_id()
                reactions_to_remove.append(removal_id)
        # ---->
        # removes the rxns we need to remove in place vs. making a new copy
        service.remove_reactions_in_place(self.model, reactions_to_remove)
        # Next, add all the reactions that aren't already in the translation:
        # Add the GENE_NO_MATCH reactions:
        for rxn_id in self.rxn_labels['gene-no-match']:
            reaction = self.rxn_labels['gene-no-match'][rxn_id]
            if reaction.is_special_ref():
                specials.append(reaction)
            else:
                super_rxns[rxn_id] = (reaction.get_rxn_ref(), reaction.get_comp_ref(), reaction.get_direction())
        adjustments = []
        # Add the RECON reactions:
        for rxn_id in self.rxn_labels['recon']:
            reaction = self.rxn_labels['recon'][rxn_id]
            if rxn_id in src_rxns:
                direction = _general_direction(reaction, src_rxns[rxn_id])
            else:
                direction = reaction.get_direction()
            if reaction.is_special_ref():
                specials.append(reaction)
            else:
                if rxn_id not in super_rxns:
                    super_rxns[rxn_id] = (reaction.get_rxn_ref(), reaction.get_comp_ref(), direction, str(reaction.gpr))
                    adjustments.append((reaction.get_removal_id(), reaction.gpr))
        # ---->
        super_rxns = super_rxns.values()
        result = service.add_reactions(self.model, super_rxns, name='super_model')
        self.model = FBAModel(result[0], result[1])
        service.adjust_gprs(self.model, adjustments)
        result = service.add_reactions_manually(self.model, specials, name='super_modelspc')
        self.model = FBAModel(result[0], result[1])

    def prepare_supermodel(self, fill_src=False):
        """
        Composition of the first several steps in the algorithm

        1) Fill the source model to media using probabilistic gapfilling (can be skipped if fill_src keyword arg is set to False)
        2) Translate the src_model to a pouplate morph.trans_model
        3) Draft reconstruction of target genome fills morph.recon_model field
        4) label reactions in the morph (populates morph.rxn_labels)
        5) Builds a super_model and puts it in the morph.model field. The model is now ready for the process_reactions function

        Note
        ----
        Function Requirements:
            - morph.probanno, morph.probannows form a valid ObjectIdentity for a readable RxnProbs object in KBase
            - morph.src_model, morph.src_modelws form a valid ObjectIdentity for a readable model object in KBase
            - morph.media, morph.mediaws form a valid ObjectIdentity for a readable media object in KBase
            - morph.genome, morph.genomews form a valid ObjectIdentity for a readable genome object in KBase
            - morph.protcomp, morph.protcompws form a valid ObjectIdentity for a readable protein comparison object in KBase
            - morph.ws_id is the ID of a writeable KBase workspace

        Parameters
        ----------
        morph: Morph
            An initialized Morph with the following Requirements:
                - morph.ws_id is a valid KBase workspace_id that user has permission
                to write to
                - morph has valid object identities for src_model, genome, probanno,
                protcomp (These 4 are object_ids, their ___ws counterparts are workspace_ids
                of user readable workspaces)
        fill_src: boolean,optional
            a boolean indicating that the src_model should first be filled using probabilistic gapfilling
            Optional, default is true.

        Returns
        -------
        Morph
            A Morph with the following state changes:
                - morph.model has the object_id of the super_model in KBase
                - morph.rxn_labels has the labels for the reactions in the super
                model
                - morph.probhash has the probability hash for reactions related to
                Target genome
                - morph.trans_model has the object_id of the translated model
                - morph.recon model has the object_id of the reconstruction of
                Target Genome

        Examples
        --------
        Suppose you have a morph initialized like so: (this is the output of Helpers.make_morph() )

        >>> morph = make_morph()

            probannows: 9145
            ws_name: MMws235
            src_modelws: 9145
            protcompws: 9145
            src_model: 19
            media: 18
            removed_ids: None
            mediaws: 9145
            trans_model: None
            probhash: None
            genomews: 9145
            essential_ids: None
            genome: 3
            rxn_labels: None
            model: None
            ws_id: 11444
            recon_model: None
            probanno: 15
            protcomp: 6

        A call to Client.prepare_supermodel(morph) will return a morph of this sort of form:

        >>> morph = Client.prepare_supermodel(morph)

            probannows: 9145
            ws_name: MMws235
            src_modelws: 9145
            protcompws: 9145
            src_model: 19
            media: 18
            removed_ids: None
            mediaws: 9145
            trans_model: 3
            probhash: [u'rxn00001' ... u'rxn97854']
            genomews: 9145
            essential_ids: None
            genome: 3
            rxn_labels: ['gene-no-much', 'gene-match', 'recon', 'no-gene']
            model: 5
            ws_id: 11444
            recon_model: 4
            probanno: 15
            protcomp: 6

        See Also
        --------
        fill_src_to_media
        translate_features
        reconstruct_genome
        label_reactions
        build_supermodel

        This functions post condition preps the morph for the Client.process_reactions(morph) function
        """
        if fill_src:
            self.fill_src_to_media()
        self.translate_features()
        self.reconstruct_genome()
        self.label_reactions()
        self.build_supermodel()

    def process_reactions(self, rxn_list=None, name='', process_count=0, get_count=False, iterative_models=True,
                          growth_condition=GrowthConditions.SimpleCondition()):
        """
        Attempts removal of rxn_list reactions from morph (i.e. morph.rxn_labels[label])

        Attempts removal of each reaction , keeping it only if it is essential to the objective function.
        Populates morph.essential_ids with the reaction_ids that could not be removed without breaking the model.
        morph.removed_ids is populated with the ids of the reactions that were removed. Both are populated as a dictionary of
        reaction_ids to their model_index and probability (like the entries in rxn_labels).
            e.g. reaction_id -> (model_index, probability)

        if rxn_list is None, the function removes (in low to high probability order) gene-no-match reactions followed by no-gene reactions

        Controlling name and process_count parameters allows the user tocontrol the number of models created in the morph.ws_id

        Note
        ----
        Function Requirements:
            - if rxn_list is None, rxn_labels['gene-no-match'] and rxn_labels['no-gene'] must be dictionaries
            with 0 or more entries of the form reaction_id -> (model_index, probability)
            - morph.model, morph.ws_id form a valid ObjectIdentity for a readable model object in KBase
            - morph.ws_id is the ID of a writeable KBase workspace

        Parameters
        ----------
        morph: Morph
            The morph containing the model (morph.model) from which reactions will be removed
        rxn_list: list, optional
            A sorted list of tuples of the form (reaction_id, (model_index, probability)) which will be processed from morph,model
            (form is the output of removal_list() function)
            (if left out, all gene-no-match follwed by all no-gene reactions will be processed in low to high likelihood order)
        name: String, optional
            Setting name will begin all output model names with name. Default is MM
            output models are named as follows: str(name) + '-' + str(process_count)
        process_count: int, optional
            A number indicating how many reactions have been processed so far, used in nameing output models. Default is 0.
            output models are named as follows: str(name) + '-' + str(process_count)
        get_count: Boolean, optional
            A Boolean flag indicating whether the process_count should be returned with the morph (as a tuple). Used when not processing all
            reactions at once. Deafault is False

        Returns
        -------
        Morph
            A morph with a new model, and essential_ids/removed)ids used to keep track of changes
        int (Only if get_count=True)
            process_count (number of models created, used for name managing)

        Examples
        --------
        Given a morph of the form (only relevant attributes shown):
            ws_name: MMws235
            rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
            ws_id: 11444
            morph.model = 5
            morph.essential_ids = None
            morph.removed_ids = None

        >>>morph = Client.process_reactions(morph, rxn_list=Client.removal_list(morph.rxn_labels['gene-no-match'], list_range=(0, 10)))

        would process the 10 least likely gene-no-match reactions, which might produce a morph like this:

            ws_name: MMws235
            rxn_labels: ['gene-match', 'gene-no-match', 'no-gene', 'recon']
            ws_id: 11444
            morph.model = 5
            morph.essential_ids = ['rxn10316_c0', 'rxn23434_c0', 'rxn78687_c0']
            morph.removed_ids = ['rxn11123_c0', 'rxn34534_c0', 'rxn90565_c0', 'rxn78987_c0', 'rxn12321_c0', 'rxn89034_c0', 'rxn88888_c0']

        where removal of one of the reactions given by a key in morph.essential_ids would result in a model that has an objective value of 0.000 in FBA simulation

        :param get_count:
        :param process_count:
        :param name:
        :param rxn_list:
        :param iterative_models:
        :param growth_condition:
        """
        ws = self.ws_id
        # Sort by probanno. items() returns (K, V=(model_index, prob))

        def get_key(item):
            return self.get_prob(item[0])

        # label argument behavior
        if rxn_list is None:
            rxn_dict = self.rxn_labels['gene-no-match']
            removal_list = sorted(rxn_dict.items(), key=get_key)
            rxn_dict = self.rxn_labels['no-gene']
            removal_list += sorted(rxn_dict.items(), key=get_key)
            # print "pre-filter: " + str(len(removal_list))
            removal_list = [r for r in removal_list if r[0] not in self.rxn_labels['common']]
            # print "post-filter: " + str(len(removal_list))
        else:
            removal_list = rxn_list
        # instantiate lists only if needed
        if self.essential_ids is None:
            self.essential_ids = dict()
        if self.removed_ids is None:
            self.removed_ids = dict()
        # Give objs a general name if none is provided
        if name == '':
            name = 'MM'
        for i in range(len(removal_list)):
            removal_id = removal_list[i][1].get_removal_id()
            rxn = removal_list[i][0]
            if removal_id.startswith('rxn00000'):
                self.log.add('skip', [self.model, removal_list[i][1]], [None], context='process_reactions',
                             notes=str([process_count]))
                continue
            print '\nReaction to remove: ' + str(removal_id) + " / " + str(rxn)
            # TODO Find someway to fix the behavior bug if model_id is not in ws, etc.
            info = service.remove_reaction(self.model, removal_id, output_id=name + '-' + str(process_count))
            new_model = FBAModel(info[0], info[1])
            if iterative_models:
                process_count += 1
            if growth_condition.evaluate({'morph': self, 'model': new_model}):
                # removed successfully
                self.log.add('Removed Reaction', [self.model, growth_condition.fba], [new_model],
                             context='process reactions')
                self.model = new_model
                self.removed_ids[removal_id] = removal_list[i][1]
            else:
                # essential
                self.log.add('Kept Reaction', [self.model, growth_condition.fba], [new_model],
                             context='process reactions')
                self.essential_ids[removal_id] = removal_list[i][1]
            print self.log.actions[-1].type + ' ' + str(removal_id) + ', FBA was ' + str(growth_condition.fba.objective)
        if get_count:
            return self, process_count
        return self

    def get_prob(self, rxn_id):
        '''
        returns the probanno likelihood for a reaction in a morph
        '''
        #TODO: Will Users ever have their own probannos? YES
        if self.probhash is None:
            self.probhash = self.probanno.probability_hash()
        try:
            result = self.probhash[rxn_id.split('_')[0]]
        except KeyError:
            result = -1.0
        return result

    def translate_media(self, new_media):
        """
        transfers a growing model to a new media and ensures growth in this media, gpafilling if necessary
        """
        self.media = new_media
        if not self.runfba().objective > 0:
            prev_rxns = set(([r.rxn_id() for r in self.model.get_reactions()]))
            info = service.gapfill_model(self.model, self.media, workspace=self.ws_id, rxn_probs=self.probanno)
            filled_model = FBAModel(info[0], info[1])
            filled_rxns = dict([(r.rxn_id(), r) for r in filled_model.get_reactions()])
            new_reactions = set(filled_rxns.keys()) - prev_rxns
            for r in new_reactions:
                self.rxn_labels['no-gene'][r] = filled_rxns[r]
            # KBASE QUIRKS MAKE THIS LINE THE OPPOSITE OF WHAT WE WANT:
            self.model = filled_model
            assert self.runfba().objective > 0

    def get_labels(self, reaction_ids):
        """
        Given a set of reaction_ids, return the labels for the reactions

        :param reaction_ids: list<str> of reaction ids. e.g. 'rxn12345_c0'
        :return: dict<str, list<str>> of ids to list of labels
        """

        result = dict()
        for r in reaction_ids:
            result[r] = []
            for label in self.rxn_labels:
                if r in self.rxn_labels[label]:
                    result[r].append(label)
        return result
Пример #15
0
    def handle_input(cls, key):
        #TODO call handle_ui_input where handle_input is called, not inside here
        if key == "q":
            Log.add("Closing Program...")
            return ["end"]
            
        elif key in ['w','a','s','d']:
            cls.pan_camera(key)

        elif key == 'e':
            if cls.lock:
                Log.add("Trying to move ship...")
                if Board.terrain[cls.lock[0]][cls.lock[1]].identity[-1] == "Ship":
                    Log.add("Ship id positive, moving...")
                    Board.move(cls.lock[0], cls.lock[1], cls.posx, cls.posy)
                else:
                    Log.add("Not a ship")
                cls.lock = False
            else:
                s = Board.terrain[cls.posx][cls.posy].identity
                if s != ["Empty"]:
                    cls.lock = (cls.posx,cls.posy)
                    Log.add("Locked onto " +str(cls.lock))
                    if "Planet" in s:
                        planet = Board.terrain[cls.lock[0]][cls.lock[1]]
                        cls.lock = False
                        return ["terrain",planet]
                else:
                    Log.add("Nothing to lock onto")
        return cls.handle_ui_input(key)
Пример #16
0
class Database:
    # init start
    def __init__(self,user='******'):
        self.currentUser = user
        self.dataLog = Log(user)

        # if no datadir, create new
        os.makedirs(dataPath, exist_ok=True)
        self.db = loadDB(self.dataLog)
        for id in self.db:
            if self.db[id]['user'] == user:
                self.id = id
    # init end


    def showUsers(self):
        print('\tid\tnavn')
        for id in self.db:
            print(f'\t{id}\t{self.db[id]["user"]}')


    def getUserName(self):
        return self.currentUser


    def choseUser(self, id):
        while True:
            try:
                self.dataLog = Log(self.db[id]["user"])
                return self.db[id]["user"]
            except KeyError:
                return None


    def addWork(self):
        print(f'\n\tRegistrere arbeid for {self.currentUser}')
        isOK = input(f'\n\t1. ja\n\t2. nei\n\tskriv:  ')
        if isOK != '1':
            return None
        while True:
            clearScreen()
            print(f'\n\tDato i dag:\t')
            print('\t' + getWeekDay(datetime.now())+ ' ' +
                datetime.now().strftime("%d.%m.%Y"))
            print('\n\tSkriv 1 for å bruke dagens dato'+
                '\n\teller tast inn egen dato'+
                '\n\tskriv 0 for å gå til hovedmeny')
            while True:
                date = input('\n\tFromatet må være slik: 01.01.2020'+
                    '\n\tskriv: ')
                if date == '1':
                    date = datetime.now().strftime("%d.%m.%Y")
                    break
                elif date == '0':
                    return None
                else:
                    try:
                        datetime.strptime(date, '%d.%m.%Y')
                        clearScreen()
                        print('\n\tDato som er registrert:')
                        print('\t' +getWeekDay(date)+ ' ' +date)
                        print('\ter dette OK?')
                        isOK = input('\t1. ja\n\t2. nei\n\tskriv: ')
                        if isOK == '1':
                            break
                    except ValueError:
                        input('\tUgyldig format'+
                            '\n\tTrykk Enter for å fortsette')
                        clearScreen()
            while True:
                clearScreen()
                print('\n\tSkriv start tid\n\tFormatet må være slik:')
                start = input('\t08:00\n\tskriv: ')
                if len(start) != 5:
                    input('\tUgyldig format'+
                        '\n\tTrykk Enter for å fortsette')
                    continue
                try:
                    datetime.strptime(start, '%H:%M')
                    break
                except ValueError:
                    input('\tUgyldig format'+
                        '\n\tTrykk Enter for å fortsette')
                    continue
            while True:
                clearScreen()
                print('\n\tSkriv slutt tid\n\tFormatet må være slik:')
                end = input('\t16:00\n\tskriv: ')
                if len(end) != 5:
                    input('\tUgyldig format'+
                        '\n\tTrykk Enter for å fortsette')
                    continue
                if end.replace(':','') <= start.replace(':',''):
                    print('\tslutt-tiden må være etter start-tiden')
                    input('\tTrykk Enter for å gå tilbake til hovedmeny')
                    return None
                try:
                    datetime.strptime(end, '%H:%M')
                    break
                except ValueError:
                    input('\tUgyldig format'+
                        '\n\tTrykk Enter for å fortsette')
                    continue

            clearScreen()

            # prompt user confirmation
            # check valid time
            if workSummary(date,start,end) == True:
                break
            else:
                continue

        clearScreen()

        y = date[6:]  # year
        m = date[3:5] # month
        d = date[:2]  # date

        # check if exist
        if self.db[self.id]['work'] == {}:
            self.db[self.id]['work'][y] = {}
        if y not in self.db[self.id]['work']:
            self.db[self.id]['work'][y] = {}
        if m not in self.db[self.id]['work'][y]:
            self.db[self.id]['work'][y][m] = {}

        # append work
        if d in self.db[self.id]['work'][y][m]:
            clearScreen()
            print('\n\tDu har allerede registrert arbeid for')
            print(f'\t{getWeekDay(date)} {date}\n')
            print('\tDitt gamle klokkeslett er')
            print(f"\tFra: {self.db[self.id]['work'][y][m][d]['start']}")
            print(f"\tTil: {self.db[self.id]['work'][y][m][d]['end']}")
            print(f'\n\tDitt nye klokkeslett er\n\tFra: {start}\n\tTil: {end}')
            choice = input('\n\tHvilket klokkeslett er riktig?'+
                '\n\t1. det gamle\n\t2. det nye\n\tskriv: ')
            if choice == '2':
                clearScreen()
                print('\n\tOppdaterer nytt klokkeslett')
                sleep(1.5)
                self.db[self.id]['work'][y][m][d]['start'] = start
                self.db[self.id]['work'][y][m][d]['end'] = end
            else:
                clearScreen()
                print('\n\tIgnorerer nytt klokkeslett')
                sleep(1.5)
                return None
        else:
            clearScreen()
            print('\n\tOppdaterer nytt klokkeslett')
            sleep(1.5)
            self.db[self.id]['work'][y][m][d] = {'start':start,'end':end}

        self.dataLog.add(f'Added work {date} from {start} to {end}')
        updateDB(self.db)
        return None

    def removeWork(self):
        print(f'\n\tFjern arbeid for {self.currentUser}')
        isOK = input(f'\n\t1. ja\n\t2. nei\n\tskriv:  ')
        if isOK != '1':
            return None
        M = nameMonths
        while True:
            clearScreen()
            y = input('\n\tSkriv inn årstall'+
                '\n\tFor eksempel 2020\n\tskriv: ')
            clearScreen()
            if len(y) == 4 and y.isdecimal() and int(y) >= 2020:
                break

        while True:
            print('\n\tVelg en måned\n')
            for i in range(0,12,2):
                print('\t'+ str(i+1).rjust(2,' ') + ' ' + M[i].ljust(11) +
                str(i+2).rjust(2,' ') + ' ' + M[i+1].ljust(11))

            m = input('\n\t0. gå tilake\n\tskriv: ')
            if int(m) >= 1 and int(m) <= 12:
                pass
            else:
                return None
            clearScreen()
            print('\n\tÅr ' + y + '\n\tMåned ' + nameMonths[int(m)-1])

            try:
                # this only force try before starting loop
                self.db[self.id]['work'][y][m]

                while True:
                    print('\n\tVelg en dato fra listen'+
                        ' som du ønsker å fjerne\n')
                    for key in self.db[self.id]['work'][y][m]:
                        print('\t'+str(int(key))+' '+nameMonths[int(m)-1]+
                        ' Fra: '+ self.db[self.id]['work'][y][m][key]['start']+
                        ' Til: '+ self.db[self.id]['work'][y][m][key]['end'])
                    d = input('\n\t0. Gå tilbake\n\tskriv dato: ')
                    if d == '0':
                        clearScreen()
                        break
                    try:
                        self.db[self.id]['work'][y][m][d.rjust(2, '0')]
                        isOK = input('\tEr du sikker?\n\t1. ja\n\t2. nei'+
                            '\n\tskriv: ')
                        if isOK == '1':
                            del self.db[self.id]['work'][y][m][d.rjust(2, '0')]
                            self.dataLog.add('Removed work '+d+'.'+
                                nameMonths[int(m)-1]+'.'+y)
                            updateDB(self.db)
                            clearScreen()
                        else:
                            clearScreen()
                            break
                    except KeyError:
                        print('\n\tDu har ikke registrert arbeid for denne datoen')
                        input('\tTrykk Enter for å gå videre')
                        clearScreen()
                        break
            except KeyError:
                print('\n\tDu har ikke registrert arbeid for denne måneden')
                input('\tTrykk Enter for å gå videre')
                clearScreen()



    def addUser(self):
        while True:
            print('\n\tSkriv inn brukernavnet som du\n\t'+
                'ønsker å legge til\n\teller skriv 0 for å gå tilbake')
            name = input('\tskriv: ')
            if name == '0':
                return None

            for value in self.db.values():
                if name in value['user']:
                    print(f'\tBrukernavn {name} eksisterer allerede')
                    input('\tTrykk Enter for å gå videre')
                    return None

            print(f'\n\t{name} blir lagt til, er dette OK?')
            choice = input('\t1. ja\n\t2. nei\n\tskriv: ')
            if choice == '1':
                self.dataLog.add(f'Added user {name}')
                if self.db == {}:
                    self.db['1'] = {'user':name, 'work':{}}
                    input('tom')
                else:
                    for i in range(1, int(max(self.db))+2):
                        if str(i) in self.db:
                            continue
                        else:
                            self.db[str(i)] = {'user':name, 'work':{}}
                            break

                updateDB(self.db)
                return None
            else:
                return None


    def removeUser(self, userID):
        if userID in self.db:
            print('\tvil du virkelig fjerne')
            print(f'\t{self.db[userID]["user"]}')
            choice = input('\t1. ja\n\t2. nei\n\tskriv: ')
            if choice == '1':
                self.dataLog.add(f'Removed user {self.db[userID]["user"]}')
                del self.db[userID]
                updateDB(self.db)

        else:
            print(f'\tBruker med id {userID} eksisterer ikke')
            input('\tTrykk Enter for å gå videre')
Пример #17
0
class car:
    def __init__(self, logger):
        self.connection = obd.Async()
        self.log = Log()
        self.logger = logger
        self.counter = 0

    def getSpeed(self, r):
        self.log.add("SPEED", str(r.value))
        self.count()

    def getFuelLevel(self, r):
        print(r.value)
        self.log.add("FUEL_LEVEL", str(r.value))
        self.count()

    def getThrottlePosition(self, r):
        self.log.add("THROTTLE_POSITION", str(r.value))
        self.count()

    def getCoolantTemp(self, r):
        self.log.add("COOLANT_TEMP", str(r.value))
        self.count()

    def getOilPressure(self, r):
        self.log.add("RPM", str(r.value))
        self.count()

    def getLoad(self, r):
        self.log.add("ENGINE_LOAD", str(r.value))
        self.count()

    def getFuelRate(self, r):
        self.log.add("FUEL_RATE", str(r.value))
        self.count()

    def count(self):
        self.counter += 1
        if self.counter == 7:  #number of callbacks
            self.logger.write(self.log.getLog())
            self.counter = 0

    def setupCallbacks(self):
        self.connection.watch(obd.commands.SPEED, callback=self.getSpeed)
        self.connection.watch(obd.commands.FUEL_LEVEL,
                              callback=self.getFuelLevel)
        self.connection.watch(obd.commands.THROTTLE_POS,
                              callback=self.getThrottlePosition)
        self.connection.watch(obd.commands.COOLANT_TEMP,
                              callback=self.getCoolantTemp)
        self.connection.watch(
            obd.commands.RPM,
            callback=self.getOilPressure)  # change to oil pressure
        self.connection.watch(obd.commands.ENGINE_LOAD, callback=self.getLoad)
        self.connection.watch(obd.commands.FUEL_RATE,
                              callback=self.getFuelRate)

    def startLogging(self):
        self.connection.start()

    def stopLogging(self):
        self.connection.stop()

    def getStatus(self):
        return self.connection.status()
Пример #18
0
class Server(object):

    def __init__(self, peers, host, port):
        self.host = host
        self.port = port
        self.peer_id = '{}:{}'.format(host, port)

        self._logger = logging.getLogger(__name__)
        self._loop = asyncio.get_event_loop()
        self._pool = Pool(self, peers)

        # heartbeat constants and bookkeeping variables
        self._heartbeat_interval = 1000  # ms
        self._last_interval = None

        self._min_heartbeat_timeout = 2000  # ms
        self._max_heartbeat_timeout = 4000  # ms
        self._heartbeat_timeout = None
        self._last_heartbeat = None

        self.reset_heartbeat()
        self.reset_timeout()

        self._log = Log(Machine())
        self.state = State.FOLLOWER
        self.term = 0
        self.voted = None
        self.votes = set()

        self._pending_clients = {}

        self.handlers = {'append_entries_req': self.handle_append_entries_req,
                         'append_entries_resp': self.handle_append_entries_resp,
                         'request_vote_req': self.handle_request_vote_req,
                         'request_vote_resp': self.handle_request_vote_resp}

    def reset_heartbeat(self):
        self._last_heartbeat = self._loop.time()

    def reset_interval(self):
        self._last_interval = self._loop.time()

    def reset_timeout(self):
        self._heartbeat_timeout = randint(self._min_heartbeat_timeout,
                                          self._max_heartbeat_timeout) / 1000

    @property
    def stale(self):
        return self._last_heartbeat + self._heartbeat_timeout < self._loop.time()

    @staticmethod
    def decode(data):
        return json.loads(data.decode())

    @staticmethod
    def encode(data):
        return json.dumps(data).encode()

    def broadcast(self, request):
        for peer in self._pool:
            self.send_async(peer, request)

    @asyncio.coroutine
    def run(self):
        self.reset_interval()

        while True:
            self._logger.debug('state: {}, term: {}'.format(self.state,
                                                            self.term))

            if self.state == State.LEADER:
                self.append_entries()

            if self.state in (State.CANDIDATE, State.FOLLOWER) and self.stale:
                self.request_vote()

            yield from self.wait()

    @asyncio.coroutine
    def send(self, peer, request):
        """
        Send a request to a peer (if available).
        """
        transport = yield from peer.get_transport()

        if transport:
            transport.write(self.encode(request))

    def send_async(self, peer, request):
        """
        Schedule the execution
        """
        asyncio.async(self.send(peer, request))

    @asyncio.coroutine
    def wait(self):
        """
        Wait for the next interval.
        """
        tic = self._heartbeat_interval / 1000 - self._loop.time() + self._last_interval
        yield from asyncio.sleep(tic)

        self.reset_interval()

    def to_leader(self):
        self.append_entries()
        self.state = State.LEADER
        self.voted = None
        self.votes = set()

        for peer in self._pool:
            peer.match = -1
            peer.next = self._log.index + 1

    def to_follower(self, term):
        self.state = State.FOLLOWER
        self.term = term
        self.voted = None
        self.votes = set()

    def append_entries(self, peer=None):
        """
        Append entries RPC.
        """
        peers = self._pool.all() if peer is None else [peer]

        for peer in peers:
            log_entries = self._log[peer.next:]
            log_index, log_term, _ = self._log[peer.next - 1]

            request = {'rpc': 'append_entries_req',
                       'peer_id': self.peer_id,
                       'term': self.term,
                       'log_commit': self._log.commit,
                       'log_entries': log_entries,
                       'log_index': log_index,
                       'log_term': log_term,
                       }

            self.send_async(peer, request)

        self._logger.debug('broadcasting append entries')

    def request_vote(self):
        """
        Request vote RPC.
        """
        self.reset_heartbeat()
        self.reset_timeout()

        self.state = State.CANDIDATE
        self.term += 1
        self.voted = self.peer_id
        self.votes = set([self.peer_id])

        request = {'rpc': 'request_vote_req',
                   'peer_id': self.peer_id,
                   'term': self.term,
                   'log_index': self._log.index,
                   'log_term': self._log.term,
                   }

        self.broadcast(request)
        self._logger.debug('broadcasting request vote')

    def handle_peer(self, request):
        """
        Dispatch requests to the appropriate handlers.
        """
        if self.term < request['term']:
            self.to_follower(request['term'])

        return self.handlers[request['rpc']](request)

    def handle_append_entries_req(self, request):
        self._logger.debug('append entries request received')

        if request['term'] < self.term:
            return

        self.reset_heartbeat()

        log_index = request['log_index']
        log_term = request['log_term']

        if not self._log.match(log_index, log_term):
            return {'rpc': 'append_entries_resp',
                    'peer_id': self.peer_id,
                    'term': self.term,
                    'log_index': self._log.index,
                    'success': False
                    }

        log_entries = request['log_entries']
        self._log.append(log_index, log_entries)

        log_commit = request['log_commit']
        if self._log.commit < log_commit:
            index = min(self._log.index, log_commit)
            self._log.commit = index
            self._log.apply(index)

        if not log_entries:  # no need to answer, the peer might have committed
            return  # new entries but has certainly not replicated new ones

        return {'rpc': 'append_entries_resp',
                'peer_id': self.peer_id,
                'term': self.term,
                'log_index': self._log.index,
                'log_term': self._log.term,
                'success': True,
                }

    def handle_append_entries_resp(self, response):
        if response['success']:
            self._logger.debug('append entries succeeded')

            log_index = response['log_index']
            log_term = response['log_term']
            peer_id = response['peer_id']

            self._pool[peer_id].match = log_index
            self._pool[peer_id].next = log_index + 1

            if (self._log.commit < log_index and
                self._pool.ack(log_index) and log_term == self.term):
                self._log.commit = log_index
                results = self._log.apply(log_index)
                self.return_results(results)

        else:
            peer = self._pool[response['peer_id']]
            peer.next -= 1
            self.append_entries(peer)

            # self._logger.debug('append entries failed')

    def handle_request_vote_req(self, request):
        self._logger.debug('request vote request received')

        if request['term'] < self.term:
            return

        log_index = request['log_index']
        log_term = request['log_term']
        peer_id = request['peer_id']

        if self.voted in (None, peer_id) and self._log.match(log_index, log_term):
            granted = True
            self.reset_heartbeat()
        else:
            granted = False

        return {'rpc': 'request_vote_resp',
                'peer_id': self.peer_id,
                'term': self.term,
                'granted': granted,
                }

    def handle_request_vote_resp(self, response):
        if self.term == response['term'] and response['granted']:
            self.votes.add(response['peer_id'])

            if self._pool.majority(len(self.votes)):
                self.to_leader()

    def handle_client(self, cmd, transport):
        self._log.add(self.term, cmd)
        self._pending_clients[(self.term, self._log.index)] = transport
        self.append_entries()

    def return_results(self, results):
        for result in results:
            term, index, result = result
            transport = self._pending_clients.pop((term, index))
            transport.write(self.encode(result))
            transport.close()
Пример #19
0
class DCGame(Model):
    def __init__(self, adjMat, visibles, adversaries):
        self.adjMat = adjMat  #matrix that keeps track of all players and their neighbors
        self.schedule = SimultaneousActivation(
            self
        )  # An activation in which players' states are effectively updated simultaneously as opposed to sequentially
        self.numAgents = len(adjMat)
        self.terminate = False  # if all non-adversarial players have reached consensus, terminal state is achieved
        self.time = 0
        # logging information
        self.log = Log()

        # total number of color changes in a game
        self.colorChanges = 0

        # convert adjMat to adjList
        def getAdjList(adjMat):
            adjList = {key: [] for key in range(self.numAgents)}
            for node in range(self.numAgents):
                #adjList[node] = [idx for idx, value in enumerate(adjMat[node]) if value == True]
                adjList[node] = [
                    idx for idx, value in enumerate(adjMat[node])
                    if value == 'True'
                ]
            return adjList

        self.adjList = getAdjList(self.adjMat)

        ############# designate visible, adversarial, and consensus nodes #############
        self.visibleColorNodes = visibles
        self.adversarialNodes = adversaries
        self.consensusNodes = [
            n for n in range(self.numAgents) if n not in self.adversarialNodes
        ]

        # adversarial nodes and regular nodes should not overlap
        assert set(self.adversarialNodes) & set(self.consensusNodes) == set()
        # visible nodes should belong to regular nodes
        assert set(self.visibleColorNodes) & set(self.consensusNodes) == set(
            self.visibleColorNodes)

        # logging simulation configuration
        self.log.add("#visible nodes: " + str(self.visibleColorNodes))
        self.log.add("#adversarial nodes: " + str(self.adversarialNodes))
        self.log.add("#consensus nodes: " + str(self.consensusNodes) + '\n')

        ############# initialize all agents #############
        for i in range(self.numAgents):
            # if i is a visible node
            isVisibleNode = i in self.visibleColorNodes
            # if i is an adversarial
            isAdversarial = i in self.adversarialNodes
            # make sure adversarial nodes are not intersected with visible nodes
            assert isVisibleNode & isAdversarial == False

            neighbors = self.adjList[i]

            # visible color nodes in i's neighbors
            vNode = list(set(neighbors) & set(self.visibleColorNodes))

            a = GameAgent(i, isVisibleNode, isAdversarial, neighbors, vNode,
                          self)
            self.schedule.add(a)

        # instantiate all nodes' neighbors and visibleColorNodes
        for agent in self.schedule.agents:
            agent.instantiateNeighbors(self)
            agent.instantiateVisibleColorNodes(self)

        self.datacollector = DataCollector(
            model_reporters={
                "red": getRed,
                "green": getGreen
            },
            agent_reporters={"agent_color": lambda a: a.color})

    # simulate the whole model for one step
    def step(self):
        # # # if either red or green reaches consensus, terminates!
        # # in terminal state we do not collect data
        if not self.terminate:
            self.datacollector.collect(self)
            self.schedule.step()
        return self.terminate

    def simulate(self, simulationTimes):
        for i in range(simulationTimes):
            self.updateTime(i)  # update model's time
            terminate = self.step()
            if terminate:
                break

        #added by Yifan
        hasWhitePlayers = False
        if not terminate:
            # if consensus was not reached in the simulation
            for agent in self.schedule.agents:
                if not agent.isAdversarial and not agent.isVisibleNode and agent.color == "white":
                    #at least one consensus player remained white
                    hasWhitePlayers = True

        # output log file to disk
        self.log.outputLog('result/simResult.txt')
        simulatedResult = self.datacollector.get_model_vars_dataframe()
        return (simulatedResult, hasWhitePlayers)

    # update model's clock
    def updateTime(self, t):
        self.time = t

    def setTerminal(self):
        assert self.terminate == False
        self.terminate = True

    def addRecord(self, msg):
        self.log.add(msg)

    # for degub purpose only
    def outputAdjMat(self, path):
        with open(path, 'w') as fid:
            for line in self.adjMat:
                # convert list of boolean values to string values
                tline = ["1" if item else "0" for item in line]
                fid.write(' '.join(tline) + '\n')