def execute(self, time_interval):
        """
        Execute the factor over the given time interval. Note that this is normally done by the workflow,
        but can also be done on the factor directly

        :param time_interval: The time interval
        :return: self (for chaining)
        """
        logging.info('{} running from {} to {}'.format(
            self.tool.__class__.__name__, time_interval.start, time_interval.end))

        # Execute the tool to produce the output plate values
        output_plate_values = {}
        if self.input_plate:
            for ipv in self.input_plate.values:
                if ipv in self.source.streams:
                    source = self.source.streams[ipv]
                else:
                    logging.warn("{} with value {} not valid for source {}".format(
                        self.input_plate, ipv, self.source))
                    continue

                output_plate_values[ipv] = self.tool.execute(
                    source=source, interval=time_interval, input_plate_value=ipv)
        else:
            source = self.source.streams[None] if self.source else None
            if "parent_plate" in self.output_plate:
                # Get the parent plate values
                parent_plate = self._plate_manager.plates[self.output_plate["parent_plate"]]
                for ppv in parent_plate.values:
                    output_plate_values[ppv] = self.tool.execute(
                        source=source, interval=time_interval, input_plate_value=ppv)
            else:
                output_plate_values[None] = self.tool.execute(
                    source=source, interval=time_interval, input_plate_value=None)

        # Ensure that the output plate values exist
        for ipv, opv in output_plate_values.items():
            input_plate_value = ".".join("_".join(i) for i in ipv) if ipv else None
            for pv in opv:
                if ipv:
                    identifier = input_plate_value + "." + self.output_plate["meta_data_id"] + "_" + pv
                else:
                    identifier = self.output_plate["meta_data_id"] + "_" + pv
                if not self._meta_data_manager.contains(identifier):
                    self._meta_data_manager.insert(
                        tag=self.output_plate["meta_data_id"],
                        identifier=identifier,
                        parent=input_plate_value if ipv else "root",
                        data=pv
                    )

        if self.output_plate["use_provided_values"]:
            raise NotImplementedError("Currently only support using empty set and complement=True for the new plate")

        if self.output_plate["plate_id"] not in self._plate_manager.plates:
            # Create the output plate
            if self.input_plate:
                parent_plate = self.input_plate.plate_id
            else:
                if "parent_plate" in self.output_plate:
                    parent_plate = self.output_plate['parent_plate']
                else:
                    parent_plate = None
            self._plate_manager.create_plate(
                plate_id=self.output_plate["plate_id"],
                description=self.output_plate["description"],
                meta_data_id=self.output_plate["meta_data_id"],
                values=[],
                complement=True,
                parent_plate=parent_plate
            )

            logging.info("Plate with ID {} created".format(self.output_plate["plate_id"]))

        return self
def execute ( self , time_interval ) : logging . info ( '{} running from {} to {}' . format ( self . tool . __class__ . __name__ , time_interval . start , time_interval . end ) ) output_plate_values = { } if self . input_plate : for ipv in self . input_plate . values : if ipv in self . source . streams : source = self . source . streams [ ipv ] else : logging . warn ( "{} with value {} not valid for source {}" . format ( self . input_plate , ipv , self . source ) ) continue output_plate_values [ ipv ] = self . tool . execute ( source = source , interval = time_interval , input_plate_value = ipv ) else : source = self . source . streams [ None ] if self . source else None if "parent_plate" in self . output_plate : parent_plate = self . _plate_manager . plates [ self . output_plate [ "parent_plate" ] ] for ppv in parent_plate . values : output_plate_values [ ppv ] = self . tool . execute ( source = source , interval = time_interval , input_plate_value = ppv ) else : output_plate_values [ None ] = self . tool . execute ( source = source , interval = time_interval , input_plate_value = None ) for ipv , opv in output_plate_values . items ( ) : input_plate_value = "." . join ( "_" . join ( i ) for i in ipv ) if ipv else None for pv in opv : if ipv : identifier = input_plate_value + "." + self . output_plate [ "meta_data_id" ] + "_" + pv else : identifier = self . output_plate [ "meta_data_id" ] + "_" + pv if not self . _meta_data_manager . contains ( identifier ) : self . _meta_data_manager . insert ( tag = self . output_plate [ "meta_data_id" ] , identifier = identifier , parent = input_plate_value if ipv else "root" , data = pv ) if self . output_plate [ "use_provided_values" ] : raise NotImplementedError ( "Currently only support using empty set and complement=True for the new plate" ) if self . output_plate [ "plate_id" ] not in self . _plate_manager . plates : if self . input_plate : parent_plate = self . input_plate . plate_id else : if "parent_plate" in self . output_plate : parent_plate = self . output_plate [ 'parent_plate' ] else : parent_plate = None self . _plate_manager . create_plate ( plate_id = self . output_plate [ "plate_id" ] , description = self . output_plate [ "description" ] , meta_data_id = self . output_plate [ "meta_data_id" ] , values = [ ] , complement = True , parent_plate = parent_plate ) logging . info ( "Plate with ID {} created" . format ( self . output_plate [ "plate_id" ] ) ) return self
Execute the factor over the given time interval. Note that this is normally done by the workflow,
        but can also be done on the factor directly

        :param time_interval: The time interval
        :return: self (for chaining)