Create AreaDefinition for specified product.

        Projection information are hard coded for 0 degree geos projection
        Test dataset doesn't provide the values in the file container.
        Only fill values are inserted.
18779
def get_area_def(self, key, info=None):
        
        # TODO Get projection information from input file
        a = 6378169.
        h = 35785831.
        b = 6356583.8
        lon_0 = 0.
        # area_extent = (-5432229.9317116784, -5429229.5285458621,
        #                5429229.5285458621, 5432229.9317116784)
        area_extent = (-5570248.4773392612, -5567248.074173444,
                       5567248.074173444, 5570248.4773392612)
        proj_dict = {'a': float(a),
                     'b': float(b),
                     'lon_0': float(lon_0),
                     'h': float(h),
                     'proj': 'geos',
                     'units': 'm'}

        area = geometry.AreaDefinition(
            'LI_area_name',
            "LI area",
            'geosli',
            proj_dict,
            self.ncols,
            self.nlines,
            area_extent)
        self.area = area
        logger.debug("Dataset area definition: \n {}".format(area))
        return area
180292
def get_area_def(self, dsid):
        
        msg = self._get_message(self._msg_datasets[dsid])
        try:
            return self._area_def_from_msg(msg)
        except (RuntimeError, KeyError):
            raise RuntimeError("Unknown GRIB projection information")
1168602
private SpatialReferenceSystem createIfNeeded(SpatialReferenceSystem srs,
			String organization, long id) throws SQLException {

		if (srs == null) {

			if (organization
					.equalsIgnoreCase(ProjectionConstants.AUTHORITY_EPSG)) {

				switch ((int) id) {
				case ProjectionConstants.EPSG_WORLD_GEODETIC_SYSTEM:
					srs = createWgs84();
					break;
				case ProjectionConstants.EPSG_WEB_MERCATOR:
					srs = createWebMercator();
					break;
				case ProjectionConstants.EPSG_WORLD_GEODETIC_SYSTEM_GEOGRAPHICAL_3D:
					srs = createWgs84Geographical3D();
					break;
				default:
					throw new GeoPackageException(
							"Spatial Reference System not supported for metadata creation. Organization: "
									+ organization + ", id: " + id);
				}
			} else if (organization
					.equalsIgnoreCase(ProjectionConstants.AUTHORITY_NONE)) {
				switch ((int) id) {
				case ProjectionConstants.UNDEFINED_CARTESIAN:
					srs = createUndefinedCartesian();
					break;
				case ProjectionConstants.UNDEFINED_GEOGRAPHIC:
					srs = createUndefinedGeographic();
					break;
				default:
					throw new GeoPackageException(
							"Spatial Reference System not supported for metadata creation. Organization: "
									+ organization + ", id: " + id);
				}
			} else {
				throw new GeoPackageException(
						"Spatial Reference System not supported for metadata creation. Organization: "
								+ organization + ", id: " + id);
			}
		} else {
			setDefinition_12_063(srs);
		}

		return srs;
	}
55324
function BufferGeometry() {

	Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } );

	this.uuid = _Math.generateUUID();

	this.name = '';
	this.type = 'BufferGeometry';

	this.index = null;
	this.attributes = {};

	this.morphAttributes = {};

	this.groups = [];

	this.boundingBox = null;
	this.boundingSphere = null;

	this.drawRange = { start: 0, count: Infinity };

	this.userData = {};

}
730910
def get_area_def(self, dsid):
        """"""
        geocoding = self.root.find('.//Tile_Geocoding')
        epsg = geocoding.find('HORIZONTAL_CS_CODE').text
        rows = int(geocoding.find('Size[@resolution="' + str(dsid.resolution) + '"]/NROWS').text)
        cols = int(geocoding.find('Size[@resolution="' + str(dsid.resolution) + '"]/NCOLS').text)
        geoposition = geocoding.find('Geoposition[@resolution="' + str(dsid.resolution) + '"]')
        ulx = float(geoposition.find('ULX').text)
        uly = float(geoposition.find('ULY').text)
        xdim = float(geoposition.find('XDIM').text)
        ydim = float(geoposition.find('YDIM').text)
        area_extent = (ulx, uly + rows * ydim, ulx + cols * xdim, uly)
        area = geometry.AreaDefinition(
                    self.tile,
                    "On-the-fly area",
                    self.tile,
                    {'init': epsg},
                    cols,
                    rows,
                    area_extent)
        return area
77777
def _setup_xy(self,bounds,xdensity,ydensity,x,y,orientation):
        
        self.debug("bounds=%s, xdensity=%s, ydensity=%s, x=%s, y=%s, orientation=%s",bounds,xdensity,ydensity,x,y,orientation)
        # Generate vectors representing coordinates at which the pattern
        # will be sampled.

        # CB: note to myself - use slice_._scs if supplied?
        x_points,y_points = SheetCoordinateSystem(bounds,xdensity,ydensity).sheetcoordinates_of_matrixidx()

        # Generate matrices of x and y sheet coordinates at which to
        # sample pattern, at the correct orientation
        self.pattern_x, self.pattern_y = self._create_and_rotate_coordinate_arrays(x_points-x,y_points-y,orientation)
81270
def create_for_data(cls, data, format, width, height, stride=None):
        
        return cls(format, width, height, data, stride)
711225
def _add_projection_coords(ds, prod_desc, proj_var, dx, dy):
    """"""
    proj = cf_to_proj(proj_var)

    # Get projected location of lower left point
    x0, y0 = proj(prod_desc.lo1, prod_desc.la1)

    # Coordinate variable for x
    ds.createDimension('x', prod_desc.nx)
    x_var = ds.createVariable('x', np.float64, dimensions=('x',))
    x_var.units = 'm'
    x_var.long_name = 'x coordinate of projection'
    x_var.standard_name = 'projection_x_coordinate'
    x_var[:] = x0 + np.arange(prod_desc.nx) * (1000. * dx)

    # Now y
    ds.createDimension('y', prod_desc.ny)
    y_var = ds.createVariable('y', np.float64, dimensions=('y',))
    y_var.units = 'm'
    y_var.long_name = 'y coordinate of projection'
    y_var.standard_name = 'projection_y_coordinate'

    # Need to flip y because we calculated from the lower left corner, but the raster data
    # is stored with top row first.
    y_var[::-1] = y0 + np.arange(prod_desc.ny) * (1000. * dy)

    # Get the two-D lon,lat grid as well
    x, y = np.meshgrid(x_var[:], y_var[:])
    lon, lat = proj(x, y, inverse=True)
    lon_var = ds.createVariable('lon', np.float64, dimensions=('y', 'x'), wrap_array=lon)
    lon_var.long_name = 'longitude'
    lon_var.units = 'degrees_east'

    lat_var = ds.createVariable('lat', np.float64, dimensions=('y', 'x'), wrap_array=lat)
    lat_var.long_name = 'latitude'
    lat_var.units = 'degrees_north'

    ds.img_extent = (x_var[:].min(), x_var[:].max(), y_var[:].min(), y_var[:].max())
1123943
def geo2d(self, name, min=None, max=None):
        
        self.components.append((name, GEO2D))
        self.__min = min
        self.__max = max
        return self
663595
PropertyDefinition<?> createOpenCmsPropertyDefinition(CmsPropertyDefinition cmsDef) {

        return createPropDef(
            PROPERTY_PREFIX + cmsDef.getName(),
            cmsDef.getName(),
            cmsDef.getName(),
            PropertyType.STRING,
            Cardinality.SINGLE,
            Updatability.READWRITE,
            false,
            false);
    }
240812
def _get_area_def(self):
        """"""
        cfac = np.int32(self.mda['cfac'])
        lfac = np.int32(self.mda['lfac'])
        coff = np.float32(self.mda['coff'])
        loff = self._get_line_offset()

        a = self.mda['projection_parameters']['a']
        b = self.mda['projection_parameters']['b']
        h = self.mda['projection_parameters']['h']
        lon_0 = self.mda['projection_parameters']['SSP_longitude']

        nlines = int(self.mda['number_of_lines'])
        ncols = int(self.mda['number_of_columns'])

        area_extent = self.get_area_extent((nlines, ncols),
                                           (loff, coff),
                                           (lfac, cfac),
                                           h)

        proj_dict = {'a': float(a),
                     'b': float(b),
                     'lon_0': float(lon_0),
                     'h': float(h),
                     'proj': 'geos',
                     'units': 'm'}

        area = geometry.AreaDefinition(
            AREA_NAMES[self.area_id]['short'],
            AREA_NAMES[self.area_id]['long'],
            'geosmsg',
            proj_dict,
            ncols,
            nlines,
            area_extent)

        return area
1228703
def space(self):
        """"""
        args_spaces = (self.S.space, self.L.space, self.H.space)
        return ProductSpace.create(*args_spaces)
888850
def create_geotiff(name, Array, driver, ndv, xsize, ysize, geot, projection, datatype, band=1):
    '''
    
    '''
    if isinstance(datatype, np.int) == False:
        if datatype.startswith('gdal.GDT_') == False:
            datatype = eval('gdal.GDT_'+datatype)
    newfilename = name+'.tif'
    # Set nans to the original No Data Value
    Array[np.isnan(Array)] = ndv
    # Set up the dataset
    DataSet = driver.Create(newfilename, xsize, ysize, 1, datatype)
    # the '1' is for band 1.
    DataSet.SetGeoTransform(geot)
    DataSet.SetProjection(projection.ExportToWkt())
    # Write the array
    DataSet.GetRasterBand(band).WriteArray(Array)
    DataSet.GetRasterBand(band).SetNoDataValue(ndv)
    return newfilename
929028
def _make_area_from_coords(self, coords):
        """"""
        if len(coords) == 2:
            lon_sn = coords[0].attrs.get('standard_name')
            lat_sn = coords[1].attrs.get('standard_name')
            if lon_sn == 'longitude' and lat_sn == 'latitude':
                key = None
                try:
                    key = (coords[0].data.name, coords[1].data.name)
                    sdef = self.coords_cache.get(key)
                except AttributeError:
                    sdef = None
                if sdef is None:
                    sdef = SwathDefinition(*coords)
                    if key is not None:
                        self.coords_cache[key] = sdef
                sensor_str = '_'.join(self.info['sensors'])
                shape_str = '_'.join(map(str, coords[0].shape))
                sdef.name = "{}_{}_{}_{}".format(sensor_str, shape_str,
                                                 coords[0].attrs['name'],
                                                 coords[1].attrs['name'])
                return sdef
            else:
                raise ValueError(
                    'Coordinates info object missing standard_name key: ' +
                    str(coords))
        elif len(coords) != 0:
            raise NameError("Don't know what to do with coordinates " + str(
                coords))
887679
public static PolyMeshDetail buildPolyMeshDetail(Context ctx, PolyMesh mesh, CompactHeightfield chf,
            float sampleDist, float sampleMaxError) {

        ctx.startTimer("BUILD_POLYMESHDETAIL");
        if (mesh.nverts == 0 || mesh.npolys == 0) {
            return null;
        }

        PolyMeshDetail dmesh = new PolyMeshDetail();
        int nvp = mesh.nvp;
        float cs = mesh.cs;
        float ch = mesh.ch;
        float[] orig = mesh.bmin;
        int borderSize = mesh.borderSize;
        int heightSearchRadius = (int) Math.max(1, Math.ceil(mesh.maxEdgeError));

        List<Integer> tris = new ArrayList<>(512);
        float verts[] = new float[256 * 3];
        HeightPatch hp = new HeightPatch();
        int nPolyVerts = 0;
        int maxhw = 0, maxhh = 0;

        int[] bounds = new int[mesh.npolys * 4];
        float[] poly = new float[nvp * 3];

        // Find max size for a polygon area.
        for (int i = 0; i < mesh.npolys; ++i) {
            int p = i * nvp * 2;
            bounds[i * 4 + 0] = chf.width;
            bounds[i * 4 + 1] = 0;
            bounds[i * 4 + 2] = chf.height;
            bounds[i * 4 + 3] = 0;
            for (int j = 0; j < nvp; ++j) {
                if (mesh.polys[p + j] == RC_MESH_NULL_IDX) {
                    break;
                }
                int v = mesh.polys[p + j] * 3;
                bounds[i * 4 + 0] = Math.min(bounds[i * 4 + 0], mesh.verts[v + 0]);
                bounds[i * 4 + 1] = Math.max(bounds[i * 4 + 1], mesh.verts[v + 0]);
                bounds[i * 4 + 2] = Math.min(bounds[i * 4 + 2], mesh.verts[v + 2]);
                bounds[i * 4 + 3] = Math.max(bounds[i * 4 + 3], mesh.verts[v + 2]);
                nPolyVerts++;
            }
            bounds[i * 4 + 0] = Math.max(0, bounds[i * 4 + 0] - 1);
            bounds[i * 4 + 1] = Math.min(chf.width, bounds[i * 4 + 1] + 1);
            bounds[i * 4 + 2] = Math.max(0, bounds[i * 4 + 2] - 1);
            bounds[i * 4 + 3] = Math.min(chf.height, bounds[i * 4 + 3] + 1);
            if (bounds[i * 4 + 0] >= bounds[i * 4 + 1] || bounds[i * 4 + 2] >= bounds[i * 4 + 3]) {
                continue;
            }
            maxhw = Math.max(maxhw, bounds[i * 4 + 1] - bounds[i * 4 + 0]);
            maxhh = Math.max(maxhh, bounds[i * 4 + 3] - bounds[i * 4 + 2]);
        }
        hp.data = new int[maxhw * maxhh];

        dmesh.nmeshes = mesh.npolys;
        dmesh.nverts = 0;
        dmesh.ntris = 0;
        dmesh.meshes = new int[dmesh.nmeshes * 4];

        int vcap = nPolyVerts + nPolyVerts / 2;
        int tcap = vcap * 2;

        dmesh.nverts = 0;
        dmesh.verts = new float[vcap * 3];
        dmesh.ntris = 0;
        dmesh.tris = new int[tcap * 4];

        for (int i = 0; i < mesh.npolys; ++i) {
            int p = i * nvp * 2;

            // Store polygon vertices for processing.
            int npoly = 0;
            for (int j = 0; j < nvp; ++j) {
                if (mesh.polys[p + j] == RC_MESH_NULL_IDX) {
                    break;
                }
                int v = mesh.polys[p + j] * 3;
                poly[j * 3 + 0] = mesh.verts[v + 0] * cs;
                poly[j * 3 + 1] = mesh.verts[v + 1] * ch;
                poly[j * 3 + 2] = mesh.verts[v + 2] * cs;
                npoly++;
            }

            // Get the height data from the area of the polygon.
            hp.xmin = bounds[i * 4 + 0];
            hp.ymin = bounds[i * 4 + 2];
            hp.width = bounds[i * 4 + 1] - bounds[i * 4 + 0];
            hp.height = bounds[i * 4 + 3] - bounds[i * 4 + 2];
            getHeightData(ctx, chf, mesh.polys, p, npoly, mesh.verts, borderSize, hp, mesh.regs[i]);

            // Build detail mesh.
            int nverts = buildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, heightSearchRadius, chf, hp,
                    verts, tris);

            // Move detail verts to world space.
            for (int j = 0; j < nverts; ++j) {
                verts[j * 3 + 0] += orig[0];
                verts[j * 3 + 1] += orig[1] + chf.ch; // Is this offset necessary? See
                                                      // https://groups.google.com/d/msg/recastnavigation/UQFN6BGCcV0/-1Ny4koOBpkJ
                verts[j * 3 + 2] += orig[2];
            }
            // Offset poly too, will be used to flag checking.
            for (int j = 0; j < npoly; ++j) {
                poly[j * 3 + 0] += orig[0];
                poly[j * 3 + 1] += orig[1];
                poly[j * 3 + 2] += orig[2];
            }

            // Store detail submesh.
            int ntris = tris.size() / 4;

            dmesh.meshes[i * 4 + 0] = dmesh.nverts;
            dmesh.meshes[i * 4 + 1] = nverts;
            dmesh.meshes[i * 4 + 2] = dmesh.ntris;
            dmesh.meshes[i * 4 + 3] = ntris;

            // Store vertices, allocate more memory if necessary.
            if (dmesh.nverts + nverts > vcap) {
                while (dmesh.nverts + nverts > vcap) {
                    vcap += 256;
                }

                float[] newv = new float[vcap * 3];
                if (dmesh.nverts != 0) {
                    System.arraycopy(dmesh.verts, 0, newv, 0, 3 * dmesh.nverts);
                }
                dmesh.verts = newv;
            }
            for (int j = 0; j < nverts; ++j) {
                dmesh.verts[dmesh.nverts * 3 + 0] = verts[j * 3 + 0];
                dmesh.verts[dmesh.nverts * 3 + 1] = verts[j * 3 + 1];
                dmesh.verts[dmesh.nverts * 3 + 2] = verts[j * 3 + 2];
                dmesh.nverts++;
            }

            // Store triangles, allocate more memory if necessary.
            if (dmesh.ntris + ntris > tcap) {
                while (dmesh.ntris + ntris > tcap) {
                    tcap += 256;
                }
                int[] newt = new int[tcap * 4];
                if (dmesh.ntris != 0) {
                    System.arraycopy(dmesh.tris, 0, newt, 0, 4 * dmesh.ntris);
                }
                dmesh.tris = newt;
            }
            for (int j = 0; j < ntris; ++j) {
                int t = j * 4;
                dmesh.tris[dmesh.ntris * 4 + 0] = tris.get(t + 0);
                dmesh.tris[dmesh.ntris * 4 + 1] = tris.get(t + 1);
                dmesh.tris[dmesh.ntris * 4 + 2] = tris.get(t + 2);
                dmesh.tris[dmesh.ntris * 4 + 3] = getTriFlags(verts, tris.get(t + 0) * 3, tris.get(t + 1) * 3,
                        tris.get(t + 2) * 3, poly, npoly);
                dmesh.ntris++;
            }
        }

        ctx.stopTimer("BUILD_POLYMESHDETAIL");
        return dmesh;

    }
456274
int createGeometry(Geometry.Type geometry_type,
			VertexDescription description) {
		int newgeom = newGeometry_(geometry_type.value());
		if (m_vertices == null) {
			m_vertices_mp = new MultiPoint(description);
			m_vertices = (MultiPointImpl) m_vertices_mp._getImpl();
		} else
			m_vertices_mp.mergeVertexDescription(description);

		m_vertex_description = m_vertices_mp.getDescription();// this
																// description
																// will be a
																// merge of
																// existing
																// description
																// and the
																// description
																// of the
																// multi_path
		m_b_has_attributes = m_vertex_description.getAttributeCount() > 1;

		if (m_first_geometry == -1) {
			m_first_geometry = newgeom;
			m_last_geometry = newgeom;
		} else {
			setPrevGeometry_(newgeom, m_last_geometry);
			setNextGeometry_(m_last_geometry, newgeom);
			m_last_geometry = newgeom;
		}
		return newgeom;
	}
1140709
def createCellsDensity (self):
        ''' '''
        from .. import sim

        cells = []
        shape = sim.net.params.shape
        sizeX = sim.net.params.sizeX
        sizeY = sim.net.params.sizeY
        sizeZ = sim.net.params.sizeZ
        
        # calculate volume
        if shape == 'cuboid':
            volume = sizeY/1e3 * sizeX/1e3 * sizeZ/1e3  
        elif shape == 'cylinder':
            volume = sizeY/1e3 * sizeX/1e3/2 * sizeZ/1e3/2 * pi
        elif shape == 'ellipsoid':
            volume = sizeY/1e3/2.0 * sizeX/1e3/2.0 * sizeZ/1e3/2.0 * pi * 4.0 / 3.0

        for coord in ['x', 'y', 'z']:
            if coord+'Range' in self.tags:  # if user provided absolute range, convert to normalized
                self.tags[coord+'normRange'] = [point / getattr(sim.net.params, 'size'+coord.upper()) for point in self.tags[coord+'Range']]
            if coord+'normRange' in self.tags:  # if normalized range, rescale volume
                minv = self.tags[coord+'normRange'][0] 
                maxv = self.tags[coord+'normRange'][1] 
                volume = volume * (maxv-minv)

        funcLocs = None  # start with no locations as a function of density function
        if isinstance(self.tags['density'], basestring): # check if density is given as a function 
            if shape == 'cuboid':  # only available for cuboids
                strFunc = self.tags['density']  # string containing function
                strVars = [var for var in ['xnorm', 'ynorm', 'znorm'] if var in strFunc]  # get list of variables used 
                if not len(strVars) == 1:
                    print('Error: density function (%s) for population %s does not include "xnorm", "ynorm" or "znorm"'%(strFunc,self.tags['pop']))
                    return
                coordFunc = strVars[0] 
                lambdaStr = 'lambda ' + coordFunc +': ' + strFunc # convert to lambda function 
                densityFunc = eval(lambdaStr)
                minRange = self.tags[coordFunc+'Range'][0]
                maxRange = self.tags[coordFunc+'Range'][1]

                interval = 0.001  # interval of location values to evaluate func in order to find the max cell density
                maxDensity = max(list(map(densityFunc, (np.arange(minRange, maxRange, interval)))))  # max cell density 
                maxCells = volume * maxDensity  # max number of cells based on max value of density func 
                
                self.rand.Random123(int(maxDensity), sim.net.lastGid, sim.cfg.seeds['loc'])
                locsAll = minRange + ((maxRange-minRange)) * np.array([self.rand.uniform(0, 1) for i in range(int(maxCells))])  # random location values 
                locsProb = np.array(list(map(densityFunc, locsAll))) / maxDensity  # calculate normalized density for each location value (used to prune)
                allrands = np.array([self.rand.uniform(0, 1) for i in range(len(locsProb))])  # create an array of random numbers for checking each location pos 
                
                makethiscell = locsProb>allrands  # perform test to see whether or not this cell should be included (pruning based on density func)
                funcLocs = [locsAll[i] for i in range(len(locsAll)) if i in np.array(makethiscell.nonzero()[0],dtype='int')] # keep only subset of yfuncLocs based on density func
                self.tags['numCells'] = len(funcLocs)  # final number of cells after pruning of location values based on density func
                if sim.cfg.verbose: print('Volume=%.2f, maxDensity=%.2f, maxCells=%.0f, numCells=%.0f'%(volume, maxDensity, maxCells, self.tags['numCells']))
            else:
                print('Error: Density functions are only implemented for cuboid shaped networks')
                exit(0)
        else:  # NO ynorm-dep
            self.tags['numCells'] = int(self.tags['density'] * volume)  # = density (cells/mm^3) * volume (mm^3)

        # calculate locations of cells 
        self.rand.Random123(self.tags['numCells'], sim.net.lastGid, sim.cfg.seeds['loc'])
        self.rand.uniform(0, 1)
        vec = h.Vector(self.tags['numCells']*3)
        vec.setrand(self.rand)
        randLocs = np.array(vec).reshape(self.tags['numCells'], 3)  # create random x,y,z locations

        if sim.net.params.shape == 'cylinder':
            # Use the x,z random vales 
            rho = randLocs[:,0] # use x rand value as the radius rho in the interval [0, 1)
            phi = 2 * pi * randLocs[:,2] # use z rand value as the angle phi in the interval [0, 2*pi) 
            x = (1 + sqrt(rho) * cos(phi))/2.0
            z = (1 + sqrt(rho) * sin(phi))/2.0
            randLocs[:,0] = x
            randLocs[:,2] = z
    
        elif sim.net.params.shape == 'ellipsoid':
            # Use the x,y,z random vales 
            rho = np.power(randLocs[:,0], 1.0/3.0) # use x rand value as the radius rho in the interval [0, 1); cuberoot
            phi = 2 * pi * randLocs[:,1] # use y rand value as the angle phi in the interval [0, 2*pi) 
            costheta = (2 * randLocs[:,2]) - 1 # use z rand value as cos(theta) in the interval [-1, 1); ensures uniform dist 
            theta = arccos(costheta)  # obtain theta from cos(theta)
            x = (1 + rho * cos(phi) * sin(theta))/2.0
            y = (1 + rho * sin(phi) * sin(theta))/2.0
            z = (1 + rho * cos(theta))/2.0 
            randLocs[:,0] = x
            randLocs[:,1] = y
            randLocs[:,2] = z

        for icoord, coord in enumerate(['x', 'y', 'z']):
            if coord+'normRange' in self.tags:  # if normalized range, rescale random locations
                minv = self.tags[coord+'normRange'][0] 
                maxv = self.tags[coord+'normRange'][1] 
                randLocs[:,icoord] = randLocs[:,icoord] * (maxv-minv) + minv
            if funcLocs and coordFunc == coord+'norm':  # if locations for this coordinate calculated using density function
                randLocs[:,icoord] = funcLocs

        if sim.cfg.verbose and not funcLocs: print('Volume=%.4f, density=%.2f, numCells=%.0f'%(volume, self.tags['density'], self.tags['numCells']))

        for i in self._distributeCells(self.tags['numCells'])[sim.rank]:
            gid = sim.net.lastGid+i
            self.cellGids.append(gid)  # add gid list of cells belonging to this population - not needed?
            cellTags = {k: v for (k, v) in self.tags.items() if k in sim.net.params.popTagsCopiedToCells}  # copy all pop tags to cell tags, except those that are pop-specific
            cellTags['pop'] = self.tags['pop']
            cellTags['xnorm'] = randLocs[i,0]  # calculate x location (um)
            cellTags['ynorm'] = randLocs[i,1]  # calculate y location (um)
            cellTags['znorm'] = randLocs[i,2]  # calculate z location (um)
            cellTags['x'] = sizeX * randLocs[i,0]  # calculate x location (um)
            cellTags['y'] = sizeY * randLocs[i,1]  # calculate y location (um)
            cellTags['z'] = sizeZ * randLocs[i,2]  # calculate z location (um)
            cells.append(self.cellModelClass(gid, cellTags)) # instantiate Cell object
            if sim.cfg.verbose: 
                print(('Cell %d/%d (gid=%d) of pop %s, pos=(%2.f, %2.f, %2.f), on node %d, '%(i, self.tags['numCells']-1, gid, self.tags['pop'],cellTags['x'], cellTags['y'], cellTags['z'], sim.rank)))
        sim.net.lastGid = sim.net.lastGid + self.tags['numCells'] 
        return cells