def sanity_check(self): # Check file has the expected size (e.g. in case ID type is wrong) if not (self.all_bytes_used()): raise SanityCheckFailedException("File size is incorrect!") # Check sum over particle types equals total number of particles in each group grouplen = self["GroupLen"][...] grouplentype = self["GroupLenType"][...] if np.any(np.sum(grouplentype, axis=1, dtype=np.int64) != grouplen): raise SanityCheckFailedException( "GroupLen not consistent with GroupLenType!") # Each offset should be previous offset plus length if self["Nids"][...] > 1: groupoffset = self["GroupOffset"][...] if np.any(groupoffset[1:] != groupoffset[:-1] + grouplen[:-1]): raise SanityCheckFailedException( "Offsets and lengths not consistent!") # Check sum of mass over particle types equals total mass of particles in each group groupmass = self["GroupMass"][...] groupmasstype = self["GroupMassType"][...] mass_sum = np.sum(groupmasstype, axis=1, dtype=np.float64) if np.any(np.abs(mass_sum - groupmass) / groupmass > 1.0e-5): raise SanityCheckFailedException( "GroupMass not consistent with GroupMassType!")
def sanity_check(self): # Check file has the expected size (e.g. in case ID type is wrong) if not (self.all_bytes_used()): raise SanityCheckFailedException("File size is incorrect!") # Check that IDs don't contain duplicates ids = self["GroupIDs"][...] idx, counts = np.unique(ids, return_counts=True) if np.any(counts != 1): raise SanityCheckFailedException("Found duplicate IDs!")
def sanity_check(self): ngroups = self["Ngroups"][...] nids = self["Nids"][...] nfiles = self["NFiles"][...] nsubgroups = self["Nsubhalos"][...] nsubperhalo = self["NsubPerHalo"][...] firstsubofhalo = self["FirstSubOfHalo"][...] sublen = self["SubLen"][...] suboffset = self["SubOffset"][...] subparenthalo = self["SubParentHalo"][...] # Check assignment of subhalos to halos if np.sum(nsubperhalo) != nsubgroups: raise SanityCheckFailedException("Sum of NSubPerHalo is wrong") ind = nsubperhalo > 0 if np.any(firstsubofhalo[ind] < 0) or np.any( firstsubofhalo[ind] >= nsubgroups): raise SanityCheckFailedException("FirstSubOfHalo out of range") if np.any(suboffset < 0) or np.any(suboffset + sublen > nids): raise SanityCheckFailedException( "Subhalo particle index(es) out of range") # Check subhalo parent group index parent = np.repeat(np.arange(ngroups, dtype=np.int32), nsubperhalo) if np.any(subparenthalo != parent): raise SanityCheckFailedException( "Subhalo parent halo index is wrong") # Check quantities which should be finite for name in ("Halo_M_Mean200", "Halo_R_Mean200", "Halo_M_Crit200", "Halo_R_Crit200", "Halo_M_TopHat200", "Halo_R_TopHat200", "SubPos", "SubVel", "SubVelDisp", "SubVmax", "SubSpin", "SubHalfMass"): data = self[name][...] if np.any(np.logical_not(np.isfinite(data))): raise SanityCheckFailedException( "Quantity %s has non-finite value" % name) # Return None if everything looks ok return None
def sanity_check(self): ids = self["GroupIDs"][...] if np.any(ids < 0): raise SanityCheckFailedException("Found negative ID") # Split ID into particle ID and hash key key = np.right_shift(ids, 34) ids = ids - np.left_shift(key, 34) # Note: hash table size and max ID hard coded here if np.any(key < 0) or np.any(key >= 256**3): raise SanityCheckFailedException("Hash key out of range") if np.any(ids < 0) or np.any(ids > 2160**3): raise SanityCheckFailedException("Particle ID out of range") if sum(ids == 0) > 1: raise SanityCheckFailedException("Found multiple zero IDs") # Return None if everything looks ok return None
def sanity_check(self): ngroups = self["Ngroups"][...] nids = self["Nids"][...] grouplen = self["GroupLen"][...] groupoffset = self["GroupOffset"][...] if sum(grouplen) != nids: raise SanityCheckFailedException( "Sum of group sizes does not equal number of particle IDs") if any(groupoffset < 0) or any(groupoffset >= nids): raise SanityCheckFailedException("Group offset out of range") if ngroups > 1: if any(groupoffset[1:] != groupoffset[:-1] + grouplen[:-1]): raise SanityCheckFailedException( "Group offset not equal to (offset+length) of previous group" ) return None
def sanity_check(self): # Check file has the expected size (e.g. in case ID type is wrong) if not (self.all_bytes_used()): raise SanityCheckFailedException("File size is incorrect!") totnids = self["TotNids"][...] totngroups = self["TotNgroups"][...] totnsubgroups = self["TotNsubgroups"][...] # Checks on header if totnids < 0 or totngroups < 0 or totnsubgroups < 0: raise SanityCheckFailedException( "Negative number of groups/subgroups/IDs") # Checks on group properties if np.any(self["GroupLen"][...] < 0): raise SanityCheckFailedException( "Found group with non-positive length!") if totnids < 2**31: # Offsets overflow if we have too many particles (e.g. Millennium-2), # so this test is expected to fail in that case if np.any(self["GroupOffset"][...] < 0) or np.any( self["GroupOffset"][...] + self["GroupLen"][...] > totnids): raise SanityCheckFailedException( "Found group with offset out of range!") # Check pointers from groups to subgroups are sane firstsub = self["FirstSub"][...] nsubs = self["Nsubs"][...] if np.any(nsubs < 0): raise SanityCheckFailedException( "Negative number of subgroups in group!") ind = nsubs > 0 if np.any(firstsub[ind] < 0) or np.any( firstsub[ind] + nsubs[ind] > totnsubgroups): raise SanityCheckFailedException( "Found group with subgroup index out of range!") # Check some group properties that we expect to be finite and non-negative for prop in ("GroupMass", "Halo_M_Mean200", "Halo_R_Mean200", "Halo_M_Crit200", "Halo_R_Crit200", "Halo_M_TopHat200", "Halo_R_TopHat200"): data = self[prop][...] if not (np.all(np.isfinite(data))): raise Exception("Found non-finite value in dataset %s" % prop) if not (np.all(data >= 0.0)): raise Exception("Found negative value in dataset %s" % prop) # Checks on subgroup properties if np.any(self["SubLen"][...] < 0): raise SanityCheckFailedException( "Found subgroup with non-positive length!") if totnids < 2**31: # Offsets overflow if we have too many particles (e.g. Millennium-2), # so this test is expected to fail in that case if np.any(self["SubOffset"][...] < 0) or np.any( self["SubOffset"][...] + self["SubLen"][...] > totnids): raise SanityCheckFailedException( "Found group with offset out of range!") # Check some subgroup properties that we expect to be finite and (in some cases) non-negative for prop in ("SubMass", "SubPos", "SubVel", "SubCofM", "SubSpin", "SubVelDisp", "SubVmax", "SubRVmax", "SubHalfMass"): data = self[prop][...] if not (np.all(np.isfinite(data))): raise Exception("Found non-finite value in dataset %s" % prop) if not (np.all(data >= 0.0)) and prop in ("SubMass", "SubVelDisp", "SubVmax", "SubRVmax", "SubHalfMass"): raise Exception("Found negative value in dataset %s" % prop) # Check SubGrNr is in range and in the expected order subgrnr = self["SubGrNr"][...] if np.any(subgrnr < 0) or np.any(subgrnr >= totngroups): raise SanityCheckFailedException( "Subgroup's SubGrNr out of range!") if subgrnr.shape[0] > 1: if np.any(subgrnr[1:] < subgrnr[:-1]): raise SanityCheckFailedException( "Subgroup SubGrNr's are not in ascending order!")
def sanity_check(self): n = self["Header"] boxsize = self["Header"].attrs["BoxSize"] nptot = self["Header"].attrs["NumPart_Total"] hashtabsize = self["Header"].attrs["HashTabSize"] nptot = nptot[1] + (nptot[2] << 32) # Determine hashbits hashbits = 1 while hashtabsize > 2: hashtabsize /= 2 hashbits += 1 hashbits /= 3 # bits per dimension del hashtabsize # Check positions pos = self["PartType1/Coordinates"][...] if not (np.all(np.isfinite(pos))): raise SanityCheckFailedException( "Particle coordinate is not finite") if np.any(pos < 0.0) or np.any(pos > boxsize): raise SanityCheckFailedException( "Particle coordinate out of range") # (don't dealloc positions yet - needed for hash table check) # Check velocities vel = self["PartType1/Velocities"][...] if not (np.all(np.isfinite(vel))): raise SanityCheckFailedException("Particle velocity is not finite") if np.any(abs(vel) > 1.0e6): raise SanityCheckFailedException("Suspiciously high velocity") del vel # Check IDs ids = self["PartType1/ParticleIDs"][...] if np.any(ids < 0) or np.any(ids > nptot): raise SanityCheckFailedException("Particle ID out of range") del ids # Read hash table first_hash_cell = self["first_hash_cell"][...] last_hash_cell = self["last_hash_cell"][...] blockid = self["blockid"][...] # Calculate hash key for each particle key = np.zeros(pos.shape[0], dtype=np.int32) - 1 for i in range(last_hash_cell - first_hash_cell): key[blockid[i]:blockid[i + 1]] = i + first_hash_cell key[blockid[-1]:] = last_hash_cell # Convert hash keys to grid coordinates ix, iy, iz = peano_hilbert_key_inverses(key, hashbits) # Convert grid coordinates to physical coords of cell centre cellsize = boxsize / (2**hashbits) cell_pos = np.empty_like(pos) cell_pos[:, 0] = ix * cellsize + 0.5 * cellsize cell_pos[:, 1] = iy * cellsize + 0.5 * cellsize cell_pos[:, 2] = iz * cellsize + 0.5 * cellsize # Ensure all particles are within cells for i in range(3): dx = np.abs(pos[:, i] - cell_pos[:, i]) ind = dx > 0.5 * boxsize dx[ind] = boxsize - dx[ind] if any(dx > 1.001 * 0.5 * cellsize): raise SanityCheckFailedException( "Particle not in correct hash cell") # Return None if everything looks ok return None