Ejemplo n.º 1
0
class AnalysisHandler(object):
    """
    Hold functions to run and the parameters to use for them.

    Attributes
    ----------
    fns_to_run : list of functions
        The functions to run
    fn_param_list : list of tuples
        The arguments to pass to these functions.
        The arguments are passed in order, so these are positional.
    fn_kwargs_list : list of dicts
        Keyword arguments to pass to the functions to run.
    results : indexed.IndexedOrderedDict
        The results of the function calls
    verbose : bool
        Whether to print more information while running the functions.
    handle_errors : bool
        Whether to handle errors during runtime of underlying functions,
        or to crash on error.

    Parameters
    ----------
    verbose : bool, optional
        Sets the value of the verbose attribute, defaults to False.
    handle_errors : bool, optional
        Sets the value of the handle_errors attribute, defaults to False.

    """
    def __init__(self, verbose=False, handle_errors=False):
        """See help(AnalysisHandler)."""
        self.fns_to_run = []
        self.fn_params_list = []
        self.fn_kwargs_list = []
        self.results = IndexedOrderedDict()
        self.verbose = verbose
        self.handle_errors = handle_errors
        self._was_error = False

    def set_handle_errors(self, handle_errors):
        """Set the value of self.handle_errors."""
        self.handle_errors = handle_errors

    def set_verbose(self, verbose):
        """Set the value of self.verbose."""
        self.verbose = verbose

    def get_results(self):
        """Return the results."""
        return self.results

    def run_all(self):
        """Alias for run_all_fns."""
        self.run_all_fns()

    def run_all_fns(self, pbar=False):
        """Run all of the established functions."""
        self._was_error = False
        if pbar:
            pbar_ = tqdm(range(len(self.fns_to_run)))
            for i in pbar_:
                fn = self.fns_to_run[i]
                fn_params = self.fn_params_list[i]
                fn_kwargs = self.fn_kwargs_list[i]
                self._run_fn(fn, *fn_params, **fn_kwargs)
        else:
            fn_zipped = zip(self.fns_to_run, self.fn_params_list,
                            self.fn_kwargs_list)
            for (fn, fn_params, fn_kwargs) in fn_zipped:
                self._run_fn(fn, *fn_params, **fn_kwargs)
        if self._was_error:
            logging.warning("A handled error occurred while running analysis")
        self._was_error = False

    def reset(self):
        """Reset this object, clearing results and function list."""
        self.reset_func_list()
        self.reset_results()

    def reset_func_list(self):
        """Reset all functions and parameters."""
        self.fns_to_run = []
        self.fn_params_list = []
        self.fn_kwargs_list = []

    def reset_results(self):
        """Reset the results."""
        self.results = IndexedOrderedDict()

    def add_fn(self, fn, *args, **kwargs):
        """
        Add the function fn to the list with the given args and kwargs.

        Parameters
        ----------
        fn : function
            The function to add.
        *args : positional arguments
            The positional arguments to run the function with.
        **kwargs : keyword arguments
            The keyword arguments to run the function with.

        Returns
        -------
        None

        """
        self.fns_to_run.append(fn)
        self.fn_params_list.append(args)
        self.fn_kwargs_list.append(kwargs)

    def save_results(self, output_location):
        """
        Save the results of analysis to the given output location.
        
        Parameters
        ----------
        output_location : string
            Path to a csv to save results to.
    
        Returns
        -------
        None

        """
        with open(output_location, "w") as f:
            print("Saving results to {}".format(output_location))
            for k, v in self.results.items():
                f.write(k.replace(" ", "_").replace(",", "_") + "\n")
                o_str = save_mixed_dict_to_csv(v, None, save=False)
                f.write(o_str)

    def _run_fn(self, fn, *args, **kwargs):
        """
        Run the function with *args and **kwargs, not usually publicly called.

        Pass simuran_save_result as a keyword argument to control
        if the result of the function is saved or not.

        Parameters
        ----------
        fn : function
            The function to run.

        Returns
        -------
        object
            The return value of the function

        """
        if self.verbose:
            print("Running {} with params {} kwargs {}".format(
                fn, *args, **kwargs))
        if self.handle_errors:
            try:
                result = fn(*args, **kwargs)
            except BaseException as e:
                log_exception(
                    e,
                    "Running {} with args {} and kwargs {}".format(
                        fn.__name__, args, kwargs),
                )
                self._was_error = True
                result = "SIMURAN-ERROR"
        else:
            result = fn(*args, **kwargs)

        ctr = 1
        save_result = kwargs.get("simuran_save_result", True)
        save_name = str(fn.__name__)
        if save_result:
            while save_name in self.results.keys():
                save_name = str(fn.__name__) + "_{}".format(ctr)
                ctr = ctr + 1
            self.results[save_name] = result

        return result

    def __str__(self):
        """String representation of this class."""
        return "{} with functions:\n {}, args:\n {}, kwargs:\n {}".format(
            self.__class__.__name__,
            self.fns_to_run,
            self.fn_params_list,
            self.fn_kwargs_list,
        )
Ejemplo n.º 2
0
IDX_COUNT = None
prevalences_count = None
prevalences_ages_sum = None

####
#### STEP 5: Feature scaling (only age: div by age_scaler = 5)
####
matrix[:, index_cols[settings.age]] = matrix[:, index_cols[
    settings.age]] / settings.age_scaler  #scales age to allow better fitting

####
#### STEP 6: loop through post_cols
####
#loop through post_cols
start = False
for node in post_cols.keys():
    if node == settings.start_icd or settings.start_icd == "":
        start = True
    if start:
        print utils.time() + 'Work on ' + node
        ####
        #### STEP 7: calculate node statistics: get possible and real incidents, calc prevalence, incidence, mean_age
        ####
        try:
            if node == "DEATH":
                possible_incidents = matrix
            else:
                possible_incidents = matrix[functions.zero_rows(
                    matrix[:,
                           pre_cols[node]]), :]  #rows,cols = matrix.nonzero()
Ejemplo n.º 3
0
class ChurchYear(object):
    def __iter__(self):
        return ChurchYearIterator(self)

    def __init__(self, year_of_advent, calendar="ACNA_BCP2019"):

        self.calendar = Calendar.objects.filter(abbreviation=calendar).first()

        self.start_year = year_of_advent
        self.end_year = year_of_advent + 1

        self.dates = IndexedOrderedDict()

        start_date = advent(year_of_advent)
        end_date = advent(year_of_advent + 1) - timedelta(days=1)

        self.start_date = start_date
        self.end_date = end_date

        self.seasons = self._get_seasons()
        self.season_tracker = None
        # create each date
        for single_date in self.daterange(start_date, end_date):
            name = single_date.strftime("%Y-%m-%d")
            self.dates[name] = CalendarDate(single_date,
                                            calendar=self.calendar,
                                            year=self)

        # add commemorations to date
        commemorations = (Commemoration.objects.select_related(
            "rank", "cannot_occur_after__rank").filter(
                calendar__abbreviation=calendar).all())
        already_added = []
        for commemoration in commemorations:

            if not commemoration.can_occur_in_year(self.start_year):
                continue

            try:
                self.dates[commemoration.initial_date_string(
                    self.start_year)].add_commemoration(commemoration)
                already_added.append(commemoration.pk)

            except KeyError:
                pass

        for key, calendar_date in self.dates.items():

            # seasons
            self._set_season(calendar_date)

            # apply transfers
            transfers = calendar_date.apply_rules()
            new_date = (calendar_date.date +
                        timedelta(days=1)).strftime("%Y-%m-%d")
            if new_date in self.dates.keys():
                self.dates[new_date].required = transfers + self.dates[
                    new_date].required

        SetNamesAndCollects(self)

        # print(
        #     "{} = {} - {} {}".format(
        #         calendar_date.season,
        #         calendar_date.date.strftime("%a, %b, %d, %Y"),
        #         calendar_date.primary.__repr__(),
        #         "(Proper {})".format(calendar_date.proper.number) if calendar_date.proper else "",
        #         "+" if calendar_date.day_of_special_commemoration else "",
        #     )
        #
        # )
        # print(calendar_date.required, calendar_date.optional)

        # #print("{} - {} - {}".format(self.mass_year, sself.daily_mass_year, self.office_year))

    def _get_seasons(self):
        seasons = (Season.objects.filter(calendar=Calendar.objects.filter(
            abbreviation=self.calendar.abbreviation).get()).order_by(
                "order").all())
        season_mapping = {}
        for season in seasons:
            season_mapping[season.start_commemoration.name] = season
        self.seasons = season_mapping
        # print(self.seasons)

    def _set_season(self, calendar_date):

        calendar_date.season = self.season_tracker
        calendar_date.evening_season = calendar_date.season

        if not calendar_date.required:
            return

        possible_days = [feast.name for feast in calendar_date.required]

        if not self.seasons:
            self._get_seasons()

        if "The Day of Pentecost" in possible_days:
            calendar_date.season = self.season_tracker

        for match in self.seasons.keys():
            if match in possible_days:
                self.season_tracker = self.seasons[match]
                if "The Day of Pentecost" not in possible_days:
                    calendar_date.season = self.season_tracker

        calendar_date.evening_season = calendar_date.season

    @staticmethod
    def daterange(start_date, end_date):
        for n in range(int((end_date - start_date).days + 1)):
            yield start_date + timedelta(n)

    @cached_property
    def mass_year(self):

        if self.start_year % 3 == 0:
            return "A"

        if self.start_year % 3 == 1:
            return "B"

        if self.start_year % 3 == 2:
            return "C"

    @cached_property
    def daily_mass_year(self):

        return 1 if self.end_year % 2 != 0 else 2

    @cached_property
    def office_year(self):

        return "I" if self.start_year % 2 == 0 else "II"

    @cached_property
    def first_date(self):
        return self.dates[:1]

    @cached_property
    def last_date(self):
        return self.dates[-1]

    def get_date(self, date_string):
        date = to_date(date_string)
        try:
            date = self.dates[date.strftime("%Y-%m-%d")]
            date.year = self
            return date
        except KeyError:
            print(date)
            print(date.strftime("%Y-%m-%d"))
            return None
Ejemplo n.º 4
0
class HashedParameterArray(object):
    """
    This object is an append-only array which composes
    the IndexedOrderedDict in order to allow for efficient
    lookup of values and indices, the structure is effectively

    {"first_key": 0, "second_key": 1, ..., "latest_key": n}

    such that item inclusion and forwards and backwards
    (i. e. index->key and key->index) are O(1).  Note that
    items in a HashedParameterArray **must be hashable**

    Its getitem behavior defaults to access via the index
    of insertion order, e. g. array[0] returns the first
    inserted object.


    """
    def __init__(self, ordering=None):
        """
        Constructs a HashedParameterArray

        Args:
            ordering (list): initial ordering of hashable
                objects to be stored in the array
        """
        # Construct IndexedOrderedDict
        self._iod = IndexedOrderedDict()
        if ordering:
            self.extend(ordering)

    def __getitem__(self, index):
        return self._iod.keys()[index]

    def __contains__(self, item):
        return item in self._iod.keys()

    def __len__(self):
        return len(self._iod)

    def append(self, item):
        """
        Appends a value to the array

        Args:
            item: item to be inserted

        Returns:
            (int) index of the item appended, if it's found
                returns an existing index, if not, returns
                the index of the inserted (i. e. latest)
                index

        """
        if item in self._iod.keys():
            return self.get_index(item)
        # Otherwise adds item
        value = len(self._iod)
        self._iod[item] = value
        return value

    def extend(self, items):
        """
        Appends multiple items to the array

        Args:
            items ([]): items to be appended

        Returns:
            ([]) indices of appended items in the array

        """
        return [self.append(item) for item in items]

    def get_index(self, item):
        """
        Fetches the index of a given item

        Args:
            item: item to be fetched
        """
        return self._iod[item]
Ejemplo n.º 5
0
class Mesh(NodeSet, ElementSet, DofSpace):
    """ Mesh class

    Static Members:
        __type__ = "Input is not list or array!"
        __type_int__ = "Input is not int!"
        __type_str__ = "Input is not str!"
        __type_int_list__ = "Input is not int or list!"
        __type_str_list__ = "Input is not str or list!"
        __type_dof__ = "Input inod is not int or dof is not str!"
        __renumber__ = "Erasing dofs: Dof numbers will be renumbered!"
        
    Instance Members:
        coords = list of nodal coordinates
        nnod = number of nodes

        connectivity = list of element connectivities
        nele = number of elements

        nrow = number of rows (nodes)
        types = list of dof names
        dofspace = array of dof indices (idofs)
        ndof = number of degrees of freedom

        groups = list of elements in each physical group
        groupNames = names of physical groups
        ngroups = number of physical groups

        path = file path
        type = file type
        rank = number of dimensions
        doElemGroups = bool
        
    Public Methods:
        Mesh(conf, props)
        readMesh(self, type, path, rank, doElemGroups)
        readGmsh(self, path, rank, doElemGroups)
        readXML(self, path, rank)
        plotMesh(rank)
        plotDeformed(self, disp, scale, rank)
        updateGeometry(self, disp)
    """

    # Public:

    #-----------------------------------------------------------------------
    #   constructor
    #-----------------------------------------------------------------------

    def __init__(self, conf=None, props=None):
        """ Input:  conf = output properties
                    props = input properties """

        NodeSet.__init__(self)
        ElementSet.__init__(self)
        self.groups = []
        self.groupNames = IndexedOrderedDict()
        self.ngroups = 0

        if conf and props:
            # Get Props
            myProps = props.getProps("mesh")
            myConf = conf.makeProps("mesh")

            self.path = myProps.get("file")
            self.type = myProps.get("type", "Gmsh")
            self.rank = myProps.get("rank", 2)
            self.doElemGroups = myProps.get("doElemGroups", False)

            myConf.set("file", self.path)
            myConf.set("type", self.type)
            myConf.set("rank", self.rank)
            myConf.set("doElemGroups", self.doElemGroups)

            # Read Mesh
            self.readMesh(self.type, self.path, self.rank, self.doElemGroups)

            # Initialize DofSpace
            DofSpace.__init__(self, self.nnod, self.rank)

    #-----------------------------------------------------------------------
    #   readMesh
    #-----------------------------------------------------------------------

    def readMesh(self, type, path, rank, doElemGroups):
        if type == "Gmsh":
            self.readGmsh(path, rank, doElemGroups)
        elif type == "XML":
            self.readXML(path, rank, doElemGroups)
        else:
            raise ValueError("type can only be Gmsh or XML!")

    #-----------------------------------------------------------------------
    #   readGmsh
    #-----------------------------------------------------------------------

    def readGmsh(self, path=None, rank=3, doElemGroups=False):
        """ Input: path = path_to_file """

        if path is None:
            Tk().withdraw()
            self.path = filedialog.askopenfilename()
        else:
            self.path = path

        fid = open(self.path, "r")

        line = "start"

        while line:
            line = fid.readline()

            #---------------------------------------------------------------
            #   Groups
            #---------------------------------------------------------------

            if line.find('$PhysicalNames') == 0:
                data = fid.readline().split()
                self.ngroups = int(data[0])
                self.groups = [[] for _ in range(self.ngroups)]

                for _ in range(self.ngroups):
                    line = fid.readline()
                    key = int(line.split()[1])
                    qstart = line.find('"') + 1
                    qend = line.find('"', -1, 0) - 1
                    self.groupNames[key] = line[qstart:qend]

            #---------------------------------------------------------------
            #   Nodes
            #---------------------------------------------------------------

            if line.find('$Nodes') == 0:
                data = fid.readline().split()
                nnod = int(data[0])

                for _ in range(nnod):
                    data = fid.readline().split()
                    coord = [float(x) for x in data[1:rank + 1]]
                    self.addNode(coord)

            #---------------------------------------------------------------
            #   Elements
            #---------------------------------------------------------------

            if line.find('$Elements') == 0:
                data = fid.readline().split()
                nele = int(data[0])

                for iele in range(nele):
                    data = fid.readline().split()
                    ntags = int(data[2])  # number of tags

                    if ntags > 0:
                        key = int(data[3])
                        if key not in self.groupNames:
                            groupName = 'Group {}'.format(key)
                            self.groupNames[key] = groupName
                            self.ngroups += 1
                            self.groups.append([])

                    if doElemGroups is True:
                        idx = self.groupNames.keys().index(key)
                        self.groups[idx].append(iele)
                    else:
                        self.groups[0].append(iele)

                    connect = [int(x) - 1 for x in data[3 + ntags:]]
                    self.addElement(connect)
        fid.close()

        # Print nnodes, nele and ngroups
        if self.ngroups == 1:
            logging.info(
                ("Mesh read with {} nodes, {} elements and 1 group: ").format(
                    self.nnod, self.nele))
        else:
            logging.info((
                "Mesh read with {} nodes, {} elements and {} groups: ").format(
                    self.nnod, self.nele, self.ngroups))

        # Print group names and number of elements
        for key in self.groupNames:
            group_name = self.groupNames[key]
            idx = self.groupNames.keys().index(key)
            group_nele = len(self.groups[idx])
            logging.info(
                ("    {} with {} elements").format(group_name, group_nele))

    #-----------------------------------------------------------------------
    #   readXML
    #-----------------------------------------------------------------------

    def readXML(self, path=None, rank=3, doElemGroups=False):
        """ Input: self.path = self.path_to_file """
        if path is None:
            Tk().withdraw()
            self.path = filedialog.askopenfilename()
        else:
            self.path = path

        if doElemGroups is True:
            raise NotImplementedError(
                " readXML does not support doElemGroups!")
        else:
            self.groups = [[]]
            self.ngroups = 1
            self.groupNames[0] = 'Group 0'

        with open(self.path, 'r') as file:

            flag_n = False
            flag_e = False

            for line in file:

                if line.startswith("<Nodes>"):
                    flag_n = True
                elif line.startswith("</Nodes>"):
                    flag_n = False
                elif line.startswith("<Elements>"):
                    flag_e = True
                elif line.startswith("</Elements>"):
                    flag_e = False

                data = re.findall(r"[-+]?\d+ *\.\d+|[-+]?\d+", line)

                if len(data) > 0 and data[0].isdigit():

                    #-------------------------------------------------------
                    #   Nodes
                    #-------------------------------------------------------

                    if flag_n is True:
                        coord = [float(x) for x in data[1:rank + 1]]
                        self.addNode(coord)

                    #-------------------------------------------------------
                    #   Elements
                    #-------------------------------------------------------

                    if flag_e is True:
                        connect = [int(x) - 1 for x in data[1:]]
                        self.groups[0].append(int(data[0]) - 1)
                        self.addElement(connect)

        logging.info(("Mesh read with {} nodes, {} elements.").format(
            self.nnod, self.nele))

    #-----------------------------------------------------------------------
    #   plotMesh
    #-----------------------------------------------------------------------

    def plotMesh(self, rank=2):
        """ Input: rank = number of dimensions """
        # Determine whether 2D or 3D plot

        if rank == 1 or rank == 2:
            fig = plt.figure(figsize=(6, 6))
            ax = fig.add_subplot(111)
        elif rank == 3:
            fig = plt.figure(figsize=(6, 6))
            ax = fig.add_subplot(111, projection='3d')

        # Plot Mesh
        for connect in self.connectivity:
            iele = connect + [connect[0]]
            coords = self.getCoords(iele)
            ax.plot(coords[:, 0], coords[:, 1], linewidth=0.5, color='k')

        return ax

    #-----------------------------------------------------------------------
    #   plotDeformed
    #-----------------------------------------------------------------------

    def plotDeformed(self, disp, scale, rank=2):
        """ Input:  disp = displacement vector
                    scale = 
                    rank = number of dimensions """

        # Craft deformed coordinates
        deformed = self.getCoords()
        for inod in range(len(self.coords)):
            idofs = self.getDofIndices(inod)
            if idofs:  # idofs is not empty
                x = self.getCoords(inod)
                u = np.array(disp[idofs]) * scale
                deformed[inod, :] = u + x

        # Create figure
        if rank == 1 or rank == 2:
            fig = plt.figure(figsize=(6, 6))
            ax = fig.add_subplot(111)
        elif rank == 3:
            fig = plt.figure(figsize=(6, 6))
            ax = fig.add_subplot(111, projection='3d')

        # Plot deformed mesh
        for connect in self.connectivity:
            iele = connect + [connect[0]]
            coords = deformed[np.ix_(iele), :][0]
            ax.plot(coords[:, 0], coords[:, 1], linewidth=0.5, color='k')

        plt.show()

    #-----------------------------------------------------------------------
    #   updateGeometry
    #-----------------------------------------------------------------------

    def updateGeometry(self, disp):
        """ Input:  disp = displacement vector """

        for inod in range(len(self.coords)):
            idofs = self.getDofIndices(inod)
            if idofs:
                x = [a + b for a, b in zip(self.coords[inod], disp[idofs])]
                self.coords[inod] = x