def get_magic_info(self, child_type, parent_type=None, attr='er',
                       filename=None, sort_by_file_type=False):
        """
        Read er_*.txt or pmag_*.txt file.
        If no filename is provided, use er_* or pmag_* file in WD.
        If sort_by_file_type, use file header to determine child, parent types,
        instead of passing those in as arguments.
        Once file is open, parse information into dictionaries for each item.
        If the item does not yet exist, add it to the builder data object.
        Then add info to the item object as object.er_data or object.pmag_data.
        """
        parent = ''
        grandparent_type = None
        magic_name = 'er_' + child_type + '_name'
        expected_item_type = child_type
        if not filename:
            short_filename = attr + '_' + child_type + 's.txt'
            magic_file = os.path.join(self.WD, short_filename)
        else:
            short_filename = os.path.split(filename)[1]
            magic_file = filename
            attr = short_filename.split('_')[0]
        print('-I- Attempting to read {}'.format(magic_file))
        if not os.path.isfile(magic_file):
            print('-W- Could not find {}'.format(magic_file))
            return False
        # get the data from the appropriate .txt file

        data_dict, header, file_type = self.read_magic_file(magic_file, magic_name,
                                                            sort_by_file_type=sort_by_file_type)
        if not data_dict:
            print('-W- Could not read in file: {}.\n    Make sure it is a MagIC-format file'.format(magic_file))
            return False

        item_type = file_type.split('_')[1][:-1]
        # if a file was named wrong, use the type of data that is actually in that file
        if item_type != expected_item_type:
            print('-W- Expected data of type: {} but instead got: {}'.format(expected_item_type,
                                                                             item_type))
            print('-W- Using type: {}'.format(item_type))
            if item_type == 'age':
                self.get_age_info(filename)
                return 'age'
            child_type = item_type
            magic_name = 'er_' + child_type + '_name'
            ind = self.ancestry.index(child_type)
            parent_type = self.ancestry[ind+1]
            if item_type != 'location':
                grandparent_type = self.ancestry[ind+2]
            else:
                grandparent_type = ''
        if not grandparent_type:
            ind = self.ancestry.index(child_type)
            try:
                grandparent_type = self.ancestry[ind+2]
            except IndexError:
                grandparent_type = None
        child_list, child_class, child_constructor = self.data_lists[child_type]

        if parent_type:
            parent_list, parent_class, parent_constructor = self.data_lists[parent_type]
        else:
            parent_list, parent_name = None, None
        for child_name in data_dict:
            # if there is a possible parent, try to find parent object in the data model
            if parent_type:
                parent_name = data_dict[child_name].get('er_' + parent_type + '_name', '')
                parent = self.find_by_name(parent_name, parent_list)
                if parent:
                    remove_dict_headers(parent.er_data)
                    remove_dict_headers(parent.pmag_data)
            # if there should be a parent
            # (meaning there is a name for it and the child object should have a parent)
            # but none exists in the data model, go ahead and create that parent object.
            if parent_name and parent_type and not parent:
                # try to get grandparent
                grandparent = None
                grandparent_name = None
                if grandparent_type:
                    grandparent_list, grandparent_class, grandparent_constructor = self.data_lists[grandparent_type]
                    grandparent_name = data_dict[child_name]['er_' + grandparent_type + '_name']
                    grandparent = self.find_by_name(grandparent_name, grandparent_list)
                    if grandparent_name and not grandparent:
                        grandparent = grandparent_constructor(grandparent_name, None)
                parent = parent_constructor(parent_name, grandparent_name)
            # otherwise there is no parent and none can be created, so use an empty string
            elif not parent:
                parent_name = None
                parent = ''
            child = self.find_by_name(child_name, child_list)
            # if the child object does not exist yet in the data model
            if not child:
                child = child_constructor(child_name, parent_name)
            else:
                # bind parent to child and child to parent
                if parent:
                    child.set_parent(parent)
                if parent and (child not in parent.children):
                    parent.add_child(child)

            # add in the appropriate data dictionary to the child object
            if attr == 'er':
                self.update_methods[child_type](child_name, child_name, parent_name,
                                                new_er_data=data_dict[child_name])
            else:
                self.update_methods[child_type](child_name, child_name, parent_name,
                                                new_pmag_data=data_dict[child_name])
            # old way
            #child.__setattr__(attr + '_data', data_dict[child_name])
            remove_dict_headers(child.er_data)
            remove_dict_headers(child.pmag_data)
            #
        return child_type