def calculate_vgp_data(self):
        """
        Calculates VGPS for all samples, sites, and locations

        Returns
        -------
        VGP_Data : dictionary of structure {sample: {comp: data},
            site: {comp: data}, location: {comp: data}}
        """
        # get criteria if it exists else use default
        crit_data = self.read_criteria_file()
        if crit_data == None:
            crit_data = pmag.default_criteria(0)
        accept = {}
        for critrec in crit_data:
            if type(critrec) != dict:
                continue
            for key in list(critrec.keys()):
                # need to migrate specimen_dang to specimen_int_dang
                if 'IE-SPEC' in list(critrec.keys()) and 'specimen_dang' in list(critrec.keys()) and 'specimen_int_dang' not in list(critrec.keys()):
                    critrec['specimen_int_dang'] = critrec['specimen_dang']
                    del critrec['specimen_dang']
                # need to get rid of ron shaars sample_int_sigma_uT
                if 'sample_int_sigma_uT' in list(critrec.keys()):
                    critrec['sample_int_sigma'] = '%10.3e' % (
                        eval(critrec['sample_int_sigma_uT'])*1e-6)
                if key not in list(accept.keys()) and critrec[key] != '':
                    accept[key] = critrec[key]

        Ns = []
        # retrieve specimen data to calculate VGPS with
        for s in list(self.pmag_results_data['specimens'].keys()):
            for fit in self.pmag_results_data['specimens'][s]:
                if fit in self.bad_fits:
                    continue
                pars = fit.get(self.COORDINATE_SYSTEM)
                # check for interpretation data for fit
                if not pars:
                    pars = self.get_PCA_parameters(
                        s, fit, fit.tmin, fit.tmax, self.COORDINATE_SYSTEM, fit.PCA_type)
                    if not pars or 'specimen_dec' not in list(pars.keys()) or 'specimen_inc' not in list(pars.keys()):
                        print(("Could not calculate interpretation for specimen %s and fit %s while calculating VGP data, skipping this component" % (
                            s, fit.name)))
                        continue
                    pars['er_specimen_name'] = s
                    pars['specimen_comp_name'] = fit.name
                Ns.append(pars)

        SpecDirs = []
        if crit_data != None:  # use selection criteria
            for rec in Ns:  # look through everything with specimen_n for "good" data
                kill = pmag.grade(rec, accept, 'specimen_dir', data_model=2.5)
                if len(kill) == 0:  # nothing killed it
                    SpecDirs.append(rec)
        else:  # no criteria
            SpecDirs = Ns[:]  # take them all

        for i in range(len(SpecDirs)):
            if SpecDirs[i] == {}:
                continue
            specimen = SpecDirs[i]['er_specimen_name']
            SpecDirs[i]['er_sample_name'] = self.Data_hierarchy['sample_of_specimen'][specimen]
            SpecDirs[i]['er_site_name'] = self.Data_hierarchy['site_of_specimen'][specimen]
            SpecDirs[i]['er_location_name'] = self.Data_hierarchy['location_of_specimen'][specimen]

        # init VGP data
        VGP_Data = {'samples': [], 'sites': [], 'locations': []}

        # obtain lat lon data
        SiteNFO = list(self.Data_info['er_sites'].values())
        for val in SiteNFO:
            site = val['er_site_name']
            not_found = []
            # check that lat/lon columns are present and non-null
            if 'site_lat' not in val:
                not_found.append('latitude')
            elif not val['site_lat'] and val['site_lat'] is not 0:
                not_found.append('latitude')
            if 'site_lon' not in val:
                not_found.append('longitude')
            elif not val['site_lon'] and val['site_lon'] is not 0:
                not_found.append('longitude')
            if not_found == []:
                continue
            TEXT = "%s not found for site %s. Select 'yes' to enter the values now or 'no' to skip this site and all samples contained in it." % (
                str(not_found), val['er_site_name'])
            dlg = wx.MessageDialog(
                self, caption="Missing Data", message=TEXT, style=wx.YES_NO | wx.ICON_QUESTION)
            result = self.show_dlg(dlg)
            dlg.Destroy()
            if result == wx.ID_YES:
                ui_dialog = demag_dialogs.user_input(self, ['Latitude', 'Longitude'], parse_funcs=[
                                                     float, float], heading="Missing Latitude or Longitude data for site: %s" % val['er_site_name'])
                self.show_dlg(ui_dialog)
                ui_data = ui_dialog.get_values()
                if ui_data[0]:
                    self.Data_info['er_sites'][site]['site_lat'] = ui_data[1]['Latitude']
                    self.Data_info['er_sites'][site]['site_lon'] = ui_data[1]['Longitude']
                    val['site_lat'] = ui_data[1]['Latitude']
                    val['site_lon'] = ui_data[1]['Longitude']

        # calculate sample vgps
        for samp in self.samples:
            SampDir = pmag.get_dictitem(SpecDirs, 'er_sample_name', samp, 'T')
            if len(SampDir) <= 0:
                continue
            for comp in self.all_fits_list:
                CompDir = pmag.get_dictitem(
                    SampDir, 'specimen_comp_name', comp, 'T')
                if len(CompDir) <= 0:
                    continue  # no data for comp
                samp_mean = pmag.lnpbykey(CompDir, 'sample', 'specimen')
                site = pmag.get_dictitem(
                    SiteNFO, 'er_site_name', CompDir[0]['er_site_name'], 'T')
                dec = float(samp_mean['sample_dec'])
                inc = float(samp_mean['sample_inc'])
                if 'sample_alpha95' in samp_mean and samp_mean['sample_alpha95'] != "":
                    a95 = float(samp_mean['sample_alpha95'])
                else:
                    a95 = 180.
                try:
                    lat = float(site[0]['site_lat'])
                    lon = float(site[0]['site_lon'])
                except (KeyError, IndexError, ValueError, TypeError) as e:
                    continue
                plong, plat, dp, dm = pmag.dia_vgp(dec, inc, a95, lat, lon)
                PmagResRec = {}
                PmagResRec['name'] = samp
                PmagResRec['comp_name'] = comp
                PmagResRec['n'] = len(CompDir)
                PmagResRec['color'] = [e.color for sl in list(self.pmag_results_data['specimens'].values(
                )) for e in sl if e not in self.bad_fits and e.name == comp][0]
                PmagResRec['vgp_lon'] = plong
                PmagResRec['vgp_lat'] = plat
                PmagResRec['lon'] = lon
                PmagResRec['lat'] = lat
                PmagResRec['vgp_dp'] = dp
                PmagResRec['vgp_dm'] = dm
                VGP_Data['samples'].append(PmagResRec)

        for site in self.sites:
            SiteDir = pmag.get_dictitem(SpecDirs, 'er_site_name', site, 'T')
            erSite = pmag.get_dictitem(SiteNFO, 'er_site_name', site, 'T')
            for comp in self.all_fits_list:
                siteD = pmag.get_dictitem(
                    SiteDir, 'specimen_comp_name', comp, 'T')
                if len(siteD) <= 0:
                    print(("no data for comp %s and site %s" % (comp, site)))
                    continue
                SiteData = pmag.lnpbykey(siteD, 'site', 'specimen')
                dec = float(SiteData['site_dec'])
                inc = float(SiteData['site_inc'])
                if 'site_alpha95' in SiteData and SiteData['site_alpha95'] != "":
                    a95 = float(SiteData['site_alpha95'])
                else:
                    a95 = 180.
                try:
                    lat = float(erSite[0]['site_lat'])
                    lon = float(erSite[0]['site_lon'])
                except (KeyError, IndexError, TypeError) as e:
                    continue
                plong, plat, dp, dm = pmag.dia_vgp(dec, inc, a95, lat, lon)
                SiteData['name'] = site
                SiteData['comp_name'] = comp
                SiteData['n'] = len(siteD)
                SiteData['vgp_lon'] = plong
                SiteData['vgp_lat'] = plat
                SiteData['lon'] = lon
                SiteData['lat'] = lat
                SiteData['vgp_dp'] = dp
                SiteData['vgp_dm'] = dm
                SiteData['color'] = [e.color for sl in list(self.pmag_results_data['specimens'].values(
                )) for e in sl if e not in self.bad_fits and e.name == comp][0]
                VGP_Data['sites'].append(SiteData)

        for loc in self.locations:
            LocDir = pmag.get_dictitem(SpecDirs, 'er_location_name', loc, 'T')
            for comp in self.all_fits_list:
                LocCompData = pmag.get_dictitem(
                    LocDir, 'specimen_comp_name', comp, 'T')
                if len(LocCompData) < 3:
                    print(("insufficient data for comp %s" % comp))
                    continue
                precs = []
                for rec in LocCompData:
                    prec = {'dec': rec['specimen_dec'], 'inc': rec['specimen_inc'],
                            'name': rec['er_site_name'], 'loc': rec['er_location_name']}
                    prec = {k: v if v != None else '' for k,
                            v in list(prec.items())}
                    precs.append(prec)
                # you need at least 3 records to get anything back from pmag.fisher_by_pol
                polpars = pmag.fisher_by_pol(precs)
                # hunt through all the modes (normal=A, reverse=B, all=ALL)
                for mode in list(polpars.keys()):
                    PolRes = {}
                    PolRes['name'] = polpars[mode]['locs']
                    PolRes["comp_name"] = comp+':'+mode
                    PolRes["dec"] = '%7.1f' % (polpars[mode]['dec'])
                    PolRes["inc"] = '%7.1f' % (polpars[mode]['inc'])
                    PolRes["n"] = '%i' % (polpars[mode]['n'])
                    PolRes["r"] = '%5.4f' % (polpars[mode]['r'])
                    PolRes["k"] = '%6.0f' % (polpars[mode]['k'])
                    PolRes['a95'] = '%7.1f' % (polpars[mode]['alpha95'])
                    dec, inc, a95 = PolRes["dec"], PolRes["inc"], PolRes["a95"]
                    lat, lon, loc_data = "", "", self.Data_info['er_locations']
                    if loc in loc_data and 'location_begin_lat' in loc_data[loc]:
                        lat = loc_data[loc]['location_begin_lat']
                    elif loc in loc_data and 'location_end_lat' in loc_data[loc]:
                        lat = loc_data[loc]['location_end_lat']
                    if loc in loc_data and 'location_begin_lon' in loc_data[loc]:
                        lon = loc_data[loc]['location_begin_lon']
                    elif loc in loc_data and 'location_end_lon' in loc_data[loc]:
                        lon = loc_data[loc]['location_end_lon']
                    if lat == "" or lon == "" or lat == None or lon == None:
                        ui_dialog = demag_dialogs.user_input(self, ['Latitude', 'Longitude'], parse_funcs=[
                                                             float, float], heading="Missing Latitude or Longitude data for location: %s" % loc)
                        self.show_dlg(ui_dialog)
                        ui_data = ui_dialog.get_values()
                        if ui_data[0]:
                            lat = ui_data[1]['Latitude']
                            lon = ui_data[1]['Longitude']
                            if loc not in loc_data:
                                loc_data[loc] = {}
                            if len(loc_data) > 0:
                                loc_data[loc]['location_begin_lat'] = lat
                                loc_data[loc]['location_begin_lon'] = lon
                        else:
                            continue
                    try:
                        plong, plat, dp, dm = pmag.dia_vgp(
                            *list(map(float, [dec, inc, a95, lat, lon])))
                    except TypeError:
                        print(("Not valid parameters for vgp calculation on location: %s" %
                               loc, dec, inc, a95, lat, lon))
                        continue
                    PolRes['vgp_lon'] = plong
                    PolRes['vgp_lat'] = plat
                    PolRes['lon'] = lon
                    PolRes['lat'] = lat
                    PolRes['vgp_dp'] = dp
                    PolRes['vgp_dm'] = dm
                    PolRes['color'] = [e.color for sl in list(self.pmag_results_data['specimens'].values(
                    )) for e in sl if e not in self.bad_fits and e.name == comp][0]
                    VGP_Data['locations'].append(PolRes)

        return VGP_Data