def main():
    """
    Command line interface for pycovjson - Converts Scientific Data Formats into CovJSON and saves to disk.

    :argument -i: Input file path.
    :argument -o: Output file name.
    :argument -t: Use Tiling.
    :argument -v: Which variable to populate coverage with.
    :argument -s: [tile shape]: Tile shape.
    :argument -n: Use interactive mode.
    :argument -u: MongoDB URL


    """
    parser = argparse.ArgumentParser(
        description='Convert Scientific Data Formats into CovJSON.')
    parser.add_argument('-i', '--input', dest='inputfile',
                        help='Name of input file', required=True)
    parser.add_argument('-o', '--output', dest='outputfile',
                        help='Name and location of output file', default='coverage.covjson')
    parser.add_argument('-t', '--tiled', action='store_true', help='Apply tiling')
    parser.add_argument('-s', '--shape', nargs='+',
                        help='Tile shape, list', type=int)
    parser.add_argument('-v', dest='variable',
                        help='Variable to populate coverage with', required=True)
    parser.add_argument('-n', '--interactive', action='store_true', help='Enter interactive mode')
    parser.add_argument('-u', '--endpoint_url', dest='endpoint_url', nargs=1, 
                        help='MongoDB endpoint for CovJSON persistence')
    args = parser.parse_args()
    inputfile = args.inputfile
    outputfile = args.outputfile
    variable = args.variable
    tiled = args.tiled
    tile_shape = args.shape
    interactive = args.interactive
    endpoint_url = args.endpoint_url

    if interactive:
        axis = input('Which Axis?', Reader.get_axis(variable))

    if tiled and len(tile_shape) == 0:
        reader = Reader(inputfile)
        shape_list = reader.get_shape(variable)
        dims = reader.get_dimensions(variable)
        print(list(zip(dims, shape_list)))
        tile_shape = input(
            'Enter the shape tile shape as a list of comma separated  integers')
        tile_shape = tile_shape.split(',')
        tile_shape = list(map(int, tile_shape))
        print(tile_shape)
    if outputfile == None:
        outputfile = outputfile.default

    Writer(outputfile, inputfile, [variable],
           tiled=tiled, tile_shape=tile_shape, endpoint_url=endpoint_url).write()
    def tile_by_axis(variable, axis):
        """

        :param variable:
        :param axis:
        :return: tile_shape
        """
        # Get shape of variable
        shape = Reader.get_shape(variable)
        # Set axis to slice by to 1
        TileSet.create_tileset()
        # Generate new tile shape
        return tile_shape
    def tile_by_axis(variable, axis):
        """

        :param variable:
        :param axis:
        :return: tile_shape
        """
        # Get shape of variable
        shape = Reader.get_shape(variable)
        # Set axis to slice by to 1
        TileSet.create_tileset()
        # Generate new tile shape
        return tile_shape
class Writer(object):
    """Writer class"""

    def __init__(self, output_name: object, dataset_path: object, vars_to_write: object, endpoint_url: object, tiled=False, tile_shape=[]) -> object:
        """
        Writer class constructor

        :parameter output_name: Name of output file
        :parameter dataset_path: Path to dataset
        :parameter vars_to_write: List of variables to write
        :parameter tiled: Boolean value (default False)
        :parameter tile_shape: List containing shape of tiles
        :parameter endpoint_url: MongoDB endpoint for CovJSON persistence
        """
        self.output_name = output_name
        self.tile_shape = tile_shape
        self.vars_to_write = vars_to_write
        self.url_template = 'localhost:8080/{t}.covjson'
        self.tiled = tiled
        if tiled:
            self.range_type = 'TiledNdArray'
        else:
            self.range_type = 'NdArray'
        self.dataset_path = dataset_path
        self.reader = Reader(dataset_path)
        self.axis_dict = self.reader.get_axes()
        self.axis_list = list(self.axis_dict.keys())
        self.ref_list = []
        if 't' in self.axis_list and 'z' in self.axis_list:
            self.ref_list.append(TemporalReferenceSystem())
            self.ref_list.append(SpatialReferenceSystem3d())

        if 't' in self.axis_list and 'z' not in self.axis_list:
            self.ref_list.append(TemporalReferenceSystem())
            self.ref_list.append(SpatialReferenceSystem2d())
        elif 't' not in self.axis_list and 'z' not in self.axis_list:
            self.ref_list.append(SpatialReferenceSystem2d())
        if endpoint_url is not None:
            self.endpoint_url = endpoint_url
        else:
            self.endpoint_url = None

    def write(self):
        """
        Writes Coverage object to local disk or MongoDB
        """

        coverage = self._construct_coverage()
        if self.endpoint_url is not None:
            if self.tiled:
                self.save_covjson_tiled(coverage, self.endpoint_url)
            else:
                self._save_covjson(coverage, self.endpoint_url)
        else:
            if self.tiled:
                self.save_covjson_tiled(coverage, self.output_name)
            else:
                self._save_covjson(coverage, self.output_name)

    def _construct_coverage(self):
        """
        Constructs Coverage object from constituent parts
        :return: coverage object
        """
        coverage = Coverage(self._construct_domain(), self._construct_range(
        ), self._construct_params(), self._construct_refs()).to_dict()
        return coverage

    def _construct_domain(self):
        """
        Constructs Domain object, populates with values
        :return: domain object
        """

        domain_type = 'Grid'
        x_values = self.reader.get_x().flatten().tolist()
        y_values = self.reader.get_y().flatten().tolist()
        t_values = []
        z_values = []

        if 't' in self.axis_list:

            t_values = self.reader.get_t()

        if 'z' in self.axis_list:

            z_values = self.reader.get_z().flatten().tolist()

        domain = Domain(domain_type, x_values, y_values, z_values, t_values)

        return domain

    def _construct_params(self):
        """
        Construct parameter object from constituent parts
        :return: Parameter object
        """
        for variable in self.vars_to_write:
            description = self.reader.get_std_name(variable)
            unit = self.reader.get_units(variable)
            symbol = self.reader.dataset[variable].units
            label = self.reader.dataset[variable].long_name
            params = Parameter(description=description, variable_name=variable,
                               symbol=symbol, unit=unit, observed_property=label)

        return params

    def _construct_refs(self):
        """
        Construct reference object
        :return: refs
        """
        refs = Reference(self.ref_list)

        return refs

    def _construct_range(self):
        """
       Construct range object
       :return: range
       """
        for variable in self.vars_to_write:
            print("Constructing Range from variable:", variable)

            axis_names = list(map(str.lower, list(self.reader.get_axis(variable))))

            if self.tiled:
                tile_set_obj = TileSet(self.tile_shape, self.urlTemplate)
                variable_type = self.reader.get_type(variable)
                variable_shape = self.reader.get_shape(variable)
                print('Variable shape:', variable_shape)

                count = 0
                for tile in tile_set_obj.get_tiles(self.tile_shape, self.reader.dataset[variable].values):
                    count += 1
                    covrange = {'ranges': Range('NdArray', data_type=variable_type, axes=tile[
                                             1], shape=variable_shape, values=tile[0].flatten().tolist()).to_dict()}
                    self.save_covjson_range(covrange, str(count) + '.covjson')
                url_template = tile_set_obj.generate_url_template(base_url='localhost:8080',
                    axis_names=['t'])
                tileset = TileSet(variable_shape, url_template).create_tileset(self.tile_shape)

                covrange = Range('TiledNdArray', data_type=variable_type, variable_name=variable,
                              axes=axis_names, tile_sets=tileset, shape=variable_shape)
                return covrange
            else:

                shape = self.reader.get_shape(variable)
                values = self.reader.get_values(variable).flatten().tolist()
                data_type = self.reader.get_type(variable)
                axes = self.reader.get_axis(variable)
                covrange = Range(range_type='NdArray',  data_type=data_type, values=values, shape=shape,
                              variable_name=variable, axes=axis_names)

                return covrange

    # Adapted from
    # https://github.com/the-iea/ecem/blob/master/preprocess/ecem/util.py -
    # letmaik
    def _save_json(self, obj, path, **kw):
        """Save json object to disk"""
        with open(path, 'w') as fp:
            print("Converting....")
            start = time.clock()
            jsonstr = json.dumps(obj, fp, cls=CustomEncoder, **kw)
            fp.write(jsonstr)
            stop = time.clock()
            print("Completed in: '%s' seconds." % (stop - start))

    def _save_covjson(self, obj, resource):
        """
        Skip indentation of certain fields to make JSON more compact but still human readable
        :param obj: the CovJSON object to write
        :param resource: either a local file path or a MongoDB endpoint

        """

        for axis in obj['domain']['axes'].values():
            self.compact(axis, 'values')
        for ref in obj['domain']['referencing']:
            self.no_indent(ref, 'coordinates')
        for covrange in obj['ranges'].values():
            self.no_indent(covrange, 'axisNames', 'shape')
            self.compact(covrange, 'values')
        self.save_json(obj, resource, indent=2)

    def save_covjson_tiled(self, obj, resource):
        """
        Skip indentation of certain fields to make JSON more compact but still human readable
        :param obj: the CovJSON object to write
        :param resource: either a local file path or a MongoDB endpoint
        """

        for axis in obj['domain']['axes'].values():
            self.compact(axis, 'values')
        for ref in obj['domain']['referencing']:
            self.no_indent(ref, 'coordinates')

        self.save_json(obj, resource, indent=2)

    def save_json(self, obj, resource, **kw):
        print("Attempting to write CovJSON manifestation to '%s'" % (resource))
        start = time.clock()
        if resource[0].startswith('mongo'):
            mongo_client = MongoDBClient(obj, resource).write()
        else:
            with open(resource, 'w') as fp:
                jsonstr = json.dumps(obj, cls=CustomEncoder, **kw)
                fp.write(jsonstr)
        stop = time.clock()
        print("Completed in: '%s' seconds." % (stop - start))

    def save_covjson_range(self, obj, path):
        for covrange in obj['ranges'].values():
            self.no_indent(covrange, 'axisNames', 'shape')
            self.compact(covrange, 'values')
        self.save_json(obj, path, indent=2)

    def compact(self, obj, *names):
        for name in names:
            obj[name] = Custom(obj[name], separators=(',', ':'))

    def no_indent(self, obj, *names):
        for name in names:
            obj[name] = Custom(obj[name])
Exemple #5
0
def main():
    """
    Command line interface for pycovjson - Converts Scientific Data Formats into CovJSON and saves to disk.

    :argument -i: Input file path.
    :argument -o: Output file name.
    :argument -t: Use Tiling.
    :argument -v: Which variable to populate coverage with.
    :argument -s: [tile shape]: Tile shape.
    :argument -n: Use interactive mode.
    :argument -u: MongoDB URL


    """
    parser = argparse.ArgumentParser(
        description='Convert Scientific Data Formats into CovJSON.')
    parser.add_argument('-i',
                        '--input',
                        dest='inputfile',
                        help='Name of input file',
                        required=True)
    parser.add_argument('-o',
                        '--output',
                        dest='outputfile',
                        help='Name and location of output file',
                        default='coverage.covjson')
    parser.add_argument('-t',
                        '--tiled',
                        action='store_true',
                        help='Apply tiling')
    parser.add_argument('-s',
                        '--shape',
                        nargs='+',
                        help='Tile shape, list',
                        type=int)
    parser.add_argument('-v',
                        dest='variable',
                        help='Variable to populate coverage with',
                        required=True)
    parser.add_argument('-n',
                        '--interactive',
                        action='store_true',
                        help='Enter interactive mode')
    parser.add_argument('-u',
                        '--endpoint_url',
                        dest='endpoint_url',
                        nargs=1,
                        help='MongoDB endpoint for CovJSON persistence')
    args = parser.parse_args()
    inputfile = args.inputfile
    outputfile = args.outputfile
    variable = args.variable
    tiled = args.tiled
    tile_shape = args.shape
    interactive = args.interactive
    endpoint_url = args.endpoint_url

    if interactive:
        axis = input('Which Axis?', Reader.get_axis(variable))

    if tiled and len(tile_shape) == 0:
        reader = Reader(inputfile)
        shape_list = reader.get_shape(variable)
        dims = reader.get_dimensions(variable)
        print(list(zip(dims, shape_list)))
        tile_shape = input(
            'Enter the shape tile shape as a list of comma separated  integers'
        )
        tile_shape = tile_shape.split(',')
        tile_shape = list(map(int, tile_shape))
        print(tile_shape)
    if outputfile == None:
        outputfile = outputfile.default

    Writer(outputfile,
           inputfile, [variable],
           tiled=tiled,
           tile_shape=tile_shape,
           endpoint_url=endpoint_url).write()