def _parse_sites(points, res_file=None): """Parse project points from list or slice Parameters ---------- points : str | pd.DataFrame | slice | list Slice specifying project points, string pointing to a project points csv, or a dataframe containing the effective csv contents. res_file : str | NoneType Optional resource file to find maximum length of project points if points slice stop is None. Returns ------- df : pd.DataFrame DataFrame mapping sites (gids) to SAM technology (config) """ df = pd.DataFrame(columns=['gid', 'config']) if isinstance(points, (list, tuple)): # explicit site list, set directly df['gid'] = points elif isinstance(points, slice): stop = points.stop if stop is None: if res_file is None: raise ValueError('Must supply a resource file if ' 'points is a slice of type ' ' slice(*, None, *)') multi_h5_res, _ = check_res_file(res_file) if multi_h5_res: stop = MultiFileResource(res_file).shape[1] else: stop = Resource(res_file).shape[1] df['gid'] = list(range(*points.indices(stop))) else: raise TypeError('Project Points sites needs to be set as a list, ' 'tuple, or slice, but was set as: {}'.format( type(points))) df['config'] = None return df
def regions(cls, regions, res_file, sam_config, tech=None, curtailment=None): """ Generate ProjectPoints for gids nearest to given latitude longitudes Parameters ---------- regions : dict Dictionary of regions to extract points for in the form: {'region': 'region_column'} res_file : str Resource file, needed to fine nearest neighbors sam_config : dict | str | list | SAMConfig SAM input configuration ID(s) and file path(s). Keys are the SAM config ID(s), top level value is the SAM path. Can also be a single config file str. If it's a list, it is mapped to the sorted list of unique configs requested by points csv. Can also be a pre loaded SAMConfig object. tech : str, optional SAM technology to analyze (pvwattsv7, windpower, tcsmoltensalt, solarwaterheat, troughphysicalheat, lineardirectsteam) The string should be lower-cased with spaces and _ removed, by default None curtailment : NoneType | dict | str | config.curtailment.Curtailment Inputs for curtailment parameters. If not None, curtailment inputs are expected. Can be: - Explicit namespace of curtailment variables (dict) - Pointer to curtailment config json file with path (str) - Instance of curtailment config object (config.curtailment.Curtailment) Returns ------- pp : ProjectPoints Initialized ProjectPoints object for points nearest to given lat_lons """ multi_h5_res, hsds = check_res_file(res_file) if multi_h5_res: res_cls = MultiFileResourceX else: res_cls = ResourceX logger.info('Extracting ProjectPoints for desired regions') points = [] with res_cls(res_file, hsds=hsds) as f: meta = f.meta for region, region_col in regions.items(): logger.debug('- {}: {}'.format(region_col, region)) # pylint: disable=no-member gids = f.region_gids(region, region_col=region_col) logger.debug('- Resource gids:\n{}'.format(gids)) if points: duplicates = np.intersect1d(gids, points).tolist() if duplicates: msg = ('reV Cannot currently handle duplicate ' 'Resource gids! The given regions containg the ' 'same gids:\n{}'.format(duplicates)) logger.error(msg) raise RuntimeError(msg) points.extend(gids.tolist()) pp = cls(points, sam_config, tech=tech, res_file=res_file, curtailment=curtailment) meta = meta.loc[pp.sites] cols = list(set(regions.values())) for c in cols: pp._df[c] = meta[c].values return pp
def lat_lon_coords(cls, lat_lons, res_file, sam_config, tech=None, curtailment=None): """ Generate ProjectPoints for gids nearest to given latitude longitudes Parameters ---------- lat_lons : str | tuple | list | ndarray Pair or pairs of latitude longitude coordinates res_file : str Resource file, needed to fine nearest neighbors sam_config : dict | str | list | SAMConfig SAM input configuration ID(s) and file path(s). Keys are the SAM config ID(s), top level value is the SAM path. Can also be a single config file str. If it's a list, it is mapped to the sorted list of unique configs requested by points csv. Can also be a pre loaded SAMConfig object. tech : str, optional SAM technology to analyze (pvwattsv7, windpower, tcsmoltensalt, solarwaterheat, troughphysicalheat, lineardirectsteam) The string should be lower-cased with spaces and _ removed, by default None curtailment : NoneType | dict | str | config.curtailment.Curtailment Inputs for curtailment parameters. If not None, curtailment inputs are expected. Can be: - Explicit namespace of curtailment variables (dict) - Pointer to curtailment config json file with path (str) - Instance of curtailment config object (config.curtailment.Curtailment) Returns ------- pp : ProjectPoints Initialized ProjectPoints object for points nearest to given lat_lons """ lat_lons = cls._parse_lat_lons(lat_lons) multi_h5_res, hsds = check_res_file(res_file) if multi_h5_res: res_cls = MultiFileResourceX res_kwargs = {} else: res_cls = ResourceX res_kwargs = {'hsds': hsds} logger.info('Converting latitude longitude coordinates into nearest ' 'ProjectPoints') logger.debug('- (lat, lon) pairs:\n{}'.format(lat_lons)) with res_cls(res_file, **res_kwargs) as f: gids = f.lat_lon_gid(lat_lons) # pylint: disable=no-member if len(gids) != len(np.unique(gids)): uniques, pos, counts = np.unique(gids, return_counts=True, return_inverse=True) duplicates = {} for idx in np.where(counts > 1)[0]: duplicate_lat_lons = lat_lons[np.where(pos == idx)[0]] duplicates[uniques[idx]] = duplicate_lat_lons msg = ('reV Cannot currently handle duplicate Resource gids! The ' 'given latitude and longitudes map to the same gids:\n{}'. format(duplicates)) logger.error(msg) raise RuntimeError(msg) gids = gids.tolist() logger.debug('- Resource gids:\n{}'.format(gids)) pp = cls(gids, sam_config, tech=tech, res_file=res_file, curtailment=curtailment) if 'points_order' in pp.df: lat_lons = lat_lons[pp.df['points_order'].values] pp._df['latitude'] = lat_lons[:, 0] pp._df['longitude'] = lat_lons[:, 1] return pp