mirror of
https://bitbucket.org/cosmicvoids/vide_public.git
synced 2025-07-04 15:21:11 +00:00
renamed src to source
This commit is contained in:
parent
4dcaf3959b
commit
4d9c5ab2c1
71 changed files with 7 additions and 3 deletions
54
python_source/misc_util/figureOutMask.py
Normal file
54
python_source/misc_util/figureOutMask.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env python
|
||||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/misc_util/figureOutMask.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
|
||||
# build a low-resolution mask given the actual galaxy positions
|
||||
|
||||
import numpy as np
|
||||
import healpy as hp
|
||||
import os
|
||||
import shutil
|
||||
import glob
|
||||
import sys
|
||||
|
||||
galFile = "path/to/galaxy/file"
|
||||
outMaskFile = "path/to/output/mask"
|
||||
|
||||
nside = 128
|
||||
npix = hp.nside2npix(nside)
|
||||
mask = np.zeros((npix))
|
||||
|
||||
for line in open(galFile):
|
||||
line = line.split()
|
||||
RA = np.float(line[3])
|
||||
Dec = np.float(line[4])
|
||||
z = np.float(line[5])
|
||||
|
||||
phi = np.pi/180.*RA
|
||||
theta = Dec*np.pi/180.
|
||||
theta = np.pi/2. - Dec*np.pi/180.
|
||||
pos = np.zeros((3))
|
||||
|
||||
pix = hp.ang2pix(nside, theta, phi)
|
||||
mask[pix] = 1.
|
||||
|
||||
print "Sky Fraction:", 1.0*len(mask[mask>0])/len(mask)
|
||||
|
||||
hp.write_map(outMaskFile, mask)
|
116
python_source/misc_util/gather_sources.py
Normal file
116
python_source/misc_util/gather_sources.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./build_tools/gather_sources.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
import shutil
|
||||
import tempfile
|
||||
import re
|
||||
from git import Repo,Tree,Blob
|
||||
|
||||
def apply_license(license, relimit, filename):
|
||||
header = re.sub(r'@FILENAME@', filename, license)
|
||||
|
||||
with open(filename) as f:
|
||||
lines = f.read()
|
||||
|
||||
lines = re.sub(relimit, lambda x: (("" if x.group(1) is None else x.group(1)) + header), lines)
|
||||
|
||||
with tempfile.NamedTemporaryFile(delete=False, mode="wt", encoding="UTF-8") as tmp_sources:
|
||||
tmp_sources.write(lines)
|
||||
|
||||
shutil.move(tmp_sources.name, filename)
|
||||
|
||||
|
||||
def apply_python_license(filename):
|
||||
license="""#+
|
||||
# VIDE -- Void IDentification and Examination -- @FILENAME@
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
"""
|
||||
|
||||
print("Shell/Python file: %s" % filename)
|
||||
relimit=r'^(#!.*\n)?#\+\n(#.*\n)*#\+\n'
|
||||
apply_license(license, relimit, filename)
|
||||
|
||||
|
||||
def apply_cpp_license(filename):
|
||||
license="""/*+
|
||||
VIDE -- Void IDentification and Examination -- @FILENAME@
|
||||
Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
Copyright (C) 2011-2014 P. M. Sutter
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+*/
|
||||
"""
|
||||
print("C++ file: %s" % filename)
|
||||
relimit = r'(?s)^()/\*\+.*\+\*/\n'
|
||||
apply_license(license, relimit, filename)
|
||||
|
||||
|
||||
def analyze_tree(prefix, t):
|
||||
for entry in t:
|
||||
ename = entry.name
|
||||
if ename == 'external' or ename == 'zobov':
|
||||
continue
|
||||
if type(entry) == Tree:
|
||||
analyze_tree(prefix + "/" + ename, entry)
|
||||
elif type(entry) == Blob:
|
||||
if re.match(".*\.(sh|py|pyx)$",ename) != None:
|
||||
fname=prefix+"/"+ename
|
||||
apply_python_license(fname)
|
||||
if re.match('.*\.(cpp|hpp|h)$', ename) != None:
|
||||
fname=prefix+"/"+ename
|
||||
apply_cpp_license(fname)
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
import sys
|
||||
if len(sys.argv) >= 2:
|
||||
apply_python_license(sys.argv[1])
|
||||
sys.exit(0)
|
||||
|
||||
repo = Repo(".")
|
||||
assert repo.bare == False
|
||||
t = repo.tree()
|
||||
analyze_tree(".", t)
|
150
python_source/pipeline_source/defaults.py
Normal file
150
python_source/pipeline_source/defaults.py
Normal file
|
@ -0,0 +1,150 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/pipeline_source/defaults.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
import os
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
# DEFAULT CONFIGURATION
|
||||
|
||||
datasetName = ""
|
||||
|
||||
startCatalogStage = 1
|
||||
endCatalogStage = 3
|
||||
continueRun = True
|
||||
|
||||
# directory for the input simulation/observational particle files
|
||||
catalogDir = os.getenv("HOME")+"/workspace/Voids/catalog/"
|
||||
|
||||
# path to HOD code
|
||||
hodPath = os.getenv("HOME")+"/projects/Voids/hod/HOD.x"
|
||||
|
||||
# where to put the final void catalog, figures, and output logs
|
||||
voidOutputDir = os.getenv("HOME")+"/workspace/Voids//"
|
||||
figDir = os.getenv("PWD")+"/../figs/"
|
||||
logDir = os.getenv("PWD")+"/../logs/"
|
||||
|
||||
# where to place the pipeline scripts
|
||||
scriptDir = os.getenv("PWD")+"/scripts//"
|
||||
|
||||
# simulation or observation?
|
||||
dataType = "simulation"
|
||||
|
||||
# available formats for simulation: gadget, mergertree
|
||||
dataFormat = "sdf"
|
||||
dataUnit = 1 # as multiple of Mpc/h
|
||||
|
||||
# place particles on the lightcone?
|
||||
useLightCone = False
|
||||
|
||||
# also do peculiar velocities?
|
||||
doPecVel = False
|
||||
|
||||
# common filename of particle files
|
||||
# use a placeholder (such as NNNNN as shown below) to select the different
|
||||
# filenames. For example, if we have partFile01, partFile02, etc.,
|
||||
# then particleFileBase = 'partFileNN'
|
||||
# particleFileDummy = 'NN'
|
||||
# fileNums = ["01", "02"]
|
||||
particleFileBase = "mf_4s_1G_512_NNNNN"
|
||||
particleFileDummy = 'NNNNN'
|
||||
|
||||
# list of file numbers for the particle files
|
||||
# to get particle file name, we replace particleFileDummy with fileNum
|
||||
fileNums = ["0.667", "0.500"]
|
||||
|
||||
# redshift of each file in the above list
|
||||
redshifts = ["0.5", "1.0"]
|
||||
|
||||
# how many independent slices along the z-axis?
|
||||
numSlices = 1
|
||||
|
||||
# how many slices for analysis?
|
||||
numAPSlices = 1
|
||||
|
||||
# how many subdivisions along the x- and y- axis?
|
||||
# ( = 2 will make 4 subvolumes for each slice, = 3 will make 9, etc.)
|
||||
numSubvolumes = 1
|
||||
|
||||
# prefix to give all outputs
|
||||
prefix = "mt_"
|
||||
|
||||
# shift the z-coord of sims with redshift
|
||||
shiftSimZ = False
|
||||
|
||||
# list of desired subsamples - see subSamplingMode parameter
|
||||
subSamples = [1.0]
|
||||
|
||||
doSubSamplingInPrep = False # do the subsampling in preparation script?
|
||||
# if False, generateMock will do the subsampling
|
||||
|
||||
# if 'absolute', subSamples are given in particles per cubic Mpc/h
|
||||
# if 'relative', subSamples are given as a fraction of input particles
|
||||
subSampleMode = "relative"
|
||||
|
||||
# common filename of halo files, leave blank to ignore halos
|
||||
haloFileBase = "mf_4s_1G_512_bgc2_NNNNN.sdf"
|
||||
haloFileDummy = 'NNNNN'
|
||||
|
||||
# minimum halo mass cuts to apply for the halo catalog
|
||||
# use "none" to get all halos
|
||||
minHaloMasses = []
|
||||
|
||||
# density threshold for halo catalogs
|
||||
haloDenList = []
|
||||
|
||||
# locations of data in the halo catalog
|
||||
haloFileMCol = 6
|
||||
haloFileXCol = 0
|
||||
haloFileYCol = 1
|
||||
haloFileZCol = 2
|
||||
haloFileVXCol = 3
|
||||
haloFileVYCol = 4
|
||||
haloFileVZCol = 5
|
||||
haloFileColSep = ','
|
||||
haloFileNumComLines = 0
|
||||
haloFilePosRescale = 1.0 # rescaling necessary to get Mpc/h
|
||||
|
||||
# adjust these two parameters given the memory contraints on your system:
|
||||
# numZobovDivisions: how many sub-volumes per dimension will zobov process
|
||||
# numZobovThreads: how many sub-volumes to process at once?
|
||||
numZobovDivisions = 2
|
||||
numZobovThreads = 2
|
||||
|
||||
# simulation information
|
||||
numPart = 512*512*512
|
||||
lbox = 999.983 # Mpc/h
|
||||
omegaM = 0.2847979853038958
|
||||
hubble = 0.6962
|
||||
|
||||
hodParmList = [
|
||||
{'name' : "dr9mid", #BOSS: Manera et al. 2012, eq. 26
|
||||
'Mmin' : 0.0,
|
||||
'M1' : 1.e14,
|
||||
'sigma_logM' : 0.596,
|
||||
'alpha' : 1.0127,
|
||||
'Mcut' : 1.19399e13,
|
||||
'galDens' : 0.0002, # density passed to HOD code
|
||||
'galDensFinal' : 0.0002, # subsample galaxies to reach this density
|
||||
},
|
||||
]
|
||||
|
||||
# END CONFIGURATION
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
1017
python_source/pipeline_source/prepareInputs.in.py
Normal file
1017
python_source/pipeline_source/prepareInputs.in.py
Normal file
File diff suppressed because it is too large
Load diff
35
python_source/setup.py
Normal file
35
python_source/setup.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/setup.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
from distutils.core import setup
|
||||
from distutils.extension import Extension
|
||||
from Cython.Distutils import build_ext
|
||||
import numpy as np
|
||||
import os
|
||||
|
||||
VOID_GSL=os.environ.get('VOID_GSL')
|
||||
|
||||
setup(
|
||||
name='vide',
|
||||
version='1.0',
|
||||
# cmdclass = {'build_ext': build_ext},
|
||||
include_dirs = [np.get_include()],
|
||||
packages=
|
||||
['vide','vide.backend','vide.voidUtil'],
|
||||
)
|
21
python_source/vide/__init__.py
Normal file
21
python_source/vide/__init__.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/__init__.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
from .backend import *
|
||||
from .voidUtil import *
|
22
python_source/vide/backend/__init__.py
Normal file
22
python_source/vide/backend/__init__.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/backend/__init__.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
from .classes import *
|
||||
from .launchers import *
|
||||
from .cosmologyTools import *
|
225
python_source/vide/backend/classes.py
Normal file
225
python_source/vide/backend/classes.py
Normal file
|
@ -0,0 +1,225 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/backend/classes.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
# classes and routines used to support scripts
|
||||
|
||||
import os
|
||||
from numpy import abs
|
||||
import matplotlib as mpl
|
||||
mpl.use('Agg')
|
||||
|
||||
LIGHT_SPEED = 299792.458
|
||||
|
||||
class Stack:
|
||||
zMin = 0.0
|
||||
zMax = 0.1
|
||||
rMin = 5
|
||||
rMax = 15
|
||||
zMinPlot = 0.0
|
||||
zMaxPlot = 0.1
|
||||
includeInHubble = True
|
||||
partOfCombo = False
|
||||
needProfile = True
|
||||
rescaleMode = "rmax" # options: "rmax" to scale to largest void in stack
|
||||
# "rv" normalize each void
|
||||
maxVoids = -1 # maximum number of voids to allow in the stack
|
||||
|
||||
def __init__(self, zMin, zMax, rMin, rMax, includeInHubble, partOfCombo,
|
||||
zMinPlot=None, needProfile=True, rescaleMode="rmax",
|
||||
maxVoids=-1, fittingMode="mcmc"):
|
||||
self.zMin = zMin
|
||||
self.zMax = zMax
|
||||
self.rMin = rMin
|
||||
self.rMax = rMax
|
||||
self.zMaxPlot = zMax
|
||||
self.includeInHubble = includeInHubble
|
||||
self.partOfCombo = partOfCombo
|
||||
self.needProfile = needProfile
|
||||
self.rescaleMode = rescaleMode
|
||||
self.maxVoids = maxVoids
|
||||
self.fittingMode = fittingMode
|
||||
|
||||
if zMinPlot == None:
|
||||
self.zMinPlot = self.zMin
|
||||
else:
|
||||
self.zMinPlot = zMinPlot
|
||||
|
||||
class Sample:
|
||||
dataType = "observation"
|
||||
dataFormat = "sdss"
|
||||
dataFile = "lss.dr72dim.dat"
|
||||
dataUnit = 1
|
||||
fullName = "lss.dr72dim.dat"
|
||||
nickName = "dim"
|
||||
zobovDir = ""
|
||||
maskFile = "rast_window_512.fits"
|
||||
selFunFile = "czselfunc.all.dr72dim.dat"
|
||||
zBoundary = (0.0, 0.1)
|
||||
zBoundaryMpc = (0., 300)
|
||||
shiftSimZ = False
|
||||
zRange = (0.0, 0.1)
|
||||
omegaM = 0.27
|
||||
minVoidRadius = -1
|
||||
fakeDensity = 0.01
|
||||
profileBinSize = 2 # Mpc
|
||||
autoNumInStack = -1 # set to >0 to automatically generate stacks of size N
|
||||
autoPartInStack = -1 # set to >0 to automatically generate stacks with N particles
|
||||
numAPSlices = 1
|
||||
volumeLimited = True
|
||||
includeInHubble = True
|
||||
partOfCombo = False
|
||||
isCombo = False
|
||||
|
||||
comboList = []
|
||||
|
||||
# applies to simulations only
|
||||
boxLen = 1024 # Mpc/h
|
||||
usePecVel = False
|
||||
subsample = 1.0
|
||||
numSubvolumes = 1
|
||||
mySubvolume = 1
|
||||
|
||||
stacks = []
|
||||
|
||||
def __init__(self, dataFile="", fullName="", dataUnit=1,
|
||||
nickName="", maskFile="", selFunFile="",
|
||||
zBoundary=(), zRange=(), zBoundaryMpc=(), shiftSimZ=False,
|
||||
minVoidRadius=-1, fakeDensity=0.01, volumeLimited=True,
|
||||
numAPSlices=1,
|
||||
includeInHubble=True, partOfCombo=False, isCombo=False,
|
||||
comboList=(), profileBinSize=2.0,
|
||||
boxLen=1024, usePecVel=False, omegaM=0.27,
|
||||
numSubvolumes=1, mySubvolume=1, dataFormat="sdss",
|
||||
useComoving=True,
|
||||
dataType="observation",
|
||||
subsample=1.0, useLightCone=False, autoNumInStack=-1,
|
||||
autoPartInStack=-1):
|
||||
self.dataFile = dataFile
|
||||
self.fullName = fullName
|
||||
self.nickName = nickName
|
||||
self.maskFile = maskFile
|
||||
self.selFunFile = selFunFile
|
||||
self.zBoundary = zBoundary
|
||||
self.zBoundaryMpc = zBoundaryMpc
|
||||
self.shiftSimZ = shiftSimZ
|
||||
self.zRange = zRange
|
||||
self.minVoidRadius = minVoidRadius
|
||||
self.fakeDensity = fakeDensity
|
||||
self.volumeLimited = volumeLimited
|
||||
self.includeInHubble = includeInHubble
|
||||
self.partOfCombo = partOfCombo
|
||||
self.isCombo = isCombo
|
||||
self.comboList = comboList
|
||||
self.numAPSlices = numAPSlices
|
||||
self.zobovDir = None
|
||||
self.profileBinSize = profileBinSize
|
||||
self.dataType = dataType
|
||||
self.boxLen = boxLen
|
||||
self.usePecVel = usePecVel
|
||||
self.omegaM = omegaM
|
||||
self.numSubvolumes = numSubvolumes
|
||||
self.mySubvolume = mySubvolume
|
||||
self.dataFormat = dataFormat
|
||||
self.subsample = subsample
|
||||
self.useLightCone = useLightCone
|
||||
self.dataUnit = dataUnit
|
||||
self.useComoving = useComoving
|
||||
self.autoNumInStack = autoNumInStack
|
||||
self.autoPartInStack = autoPartInStack
|
||||
|
||||
self.stacks = []
|
||||
|
||||
def addStack(self, zMin, zMax, rMin, rMax,
|
||||
includeInHubble, partOfCombo,zMinPlot=None,
|
||||
needProfile=True, rescaleMode="rmax",
|
||||
maxVoids=-1, fittingMode="mcmc"):
|
||||
self.stacks.append(Stack(zMin, zMax, rMin, rMax,
|
||||
includeInHubble, partOfCombo,
|
||||
zMinPlot=zMinPlot, needProfile=needProfile,
|
||||
rescaleMode=rescaleMode,
|
||||
maxVoids=maxVoids,
|
||||
fittingMode=fittingMode))
|
||||
|
||||
def getHubbleStacks(self):
|
||||
stacksForHubble = []
|
||||
for stack in self.stacks:
|
||||
if stack.includeInHubble:
|
||||
stacksForHubble.append(stack)
|
||||
return stacksForHubble
|
||||
|
||||
def getUniqueRBins(self):
|
||||
uniqueRStacks = []
|
||||
for stack in self.stacks:
|
||||
if not stack.includeInHubble:
|
||||
continue
|
||||
alreadyHere = False
|
||||
for stackCheck in uniqueRStacks:
|
||||
if stack.rMin == stackCheck.rMin and stack.rMax == stackCheck.rMax:
|
||||
alreadyHere = True
|
||||
break
|
||||
if not alreadyHere:
|
||||
uniqueRStacks.append(stack)
|
||||
return uniqueRStacks
|
||||
|
||||
def getUniqueZBins(self):
|
||||
uniqueZStacks = []
|
||||
for stack in self.stacks:
|
||||
if not stack.includeInHubble:
|
||||
continue
|
||||
alreadyHere = False
|
||||
for stackCheck in uniqueZStacks:
|
||||
if stack.zMin == stackCheck.zMin and stack.zMax == stackCheck.zMax:
|
||||
alreadyHere = True
|
||||
break
|
||||
if not alreadyHere:
|
||||
uniqueZStacks.append(stack)
|
||||
return uniqueZStacks
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
def jobSuccessful(logFile, doneString):
|
||||
jobDone = False
|
||||
checkLine = ""
|
||||
if os.access(logFile, os.F_OK):
|
||||
#filelines = file(logFile, "r").readlines()
|
||||
#if len(filelines) >= 1:
|
||||
# checkLine = filelines[-1]
|
||||
for line in open(logFile, 'r'):
|
||||
if doneString in line: jobDone = True
|
||||
return jobDone
|
||||
|
||||
def getStackSuffix(zMin, zMax, rMin, rMax, dataPortion, customLine=""):
|
||||
return "z"+str(zMin)+"-"+str(zMax)+"_"+str(rMin)+"-"+str(rMax)+\
|
||||
"Mpc"+customLine+"_"+dataPortion
|
||||
|
||||
def getPeriodic(sample):
|
||||
periodicLine = ""
|
||||
if sample.dataType != "observation":
|
||||
if sample.numSubvolumes == 1: periodicLine += "xy"
|
||||
if abs(sample.zBoundaryMpc[1] - sample.zBoundaryMpc[0] - \
|
||||
sample.boxLen) <= 1.e-1:
|
||||
periodicLine += "z"
|
||||
return periodicLine
|
||||
|
||||
def my_import(name):
|
||||
mod = __import__(name)
|
||||
components = name.split('.')
|
||||
for comp in components[1:]:
|
||||
mod = getattr(mod, comp)
|
||||
return mod
|
112
python_source/vide/backend/cosmologyTools.py
Normal file
112
python_source/vide/backend/cosmologyTools.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/apTools/chi2/cosmologyTools.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
# a suite of functions to compute expansion rates, angular diameter
|
||||
# distances, and expected void stretching
|
||||
|
||||
import numpy as np
|
||||
import scipy.integrate as integrate
|
||||
import healpy as healpy
|
||||
import os
|
||||
from vide.backend import *
|
||||
|
||||
__all__=['expansion', 'angularDiameter', 'aveExpansion', 'getSurveyProps']
|
||||
|
||||
# returns 1/E(z) for the given cosmology
|
||||
def expansion(z, Om = 0.27, Ot = 1.0, w0 = -1.0, wa = 0.0):
|
||||
ez = Om * (1+z)**3 + (Ot-Om)# * (1+z)**(3.+3*wz)
|
||||
#ez = Om * (1+z)**3 + (Ot-Om)# * integrade.quad(eosDE, 0.0, z, args=(w0,wa))[0]
|
||||
ez = 1./np.sqrt(ez)
|
||||
return ez
|
||||
|
||||
# returns DE value at redshift z
|
||||
def eosDE(z, w0 = -1.0, wa = 0.0):
|
||||
return w0 + wa*z/(1+z)
|
||||
|
||||
# returns D_A(z) for the given cosmology
|
||||
def angularDiameter(z, Om = 0.27, Ot = 1.0, w0 = -1.0, wa = 0.0):
|
||||
da = integrate.quad(expansion, 0.0, z, args=(Om, Ot, w0, wa))[0]
|
||||
return da
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# returns average expected expansion for a given redshift range
|
||||
def aveExpansion(zStart, zEnd, Om = 0.27, Ot = 1.0, w0 = -1.0, wa = 0.0):
|
||||
if zStart == 0.0: zStart = 1.e-6
|
||||
ave = integrate.quad(expansion, zStart, zEnd, args=(Om, Ot, w0, wa))[0]
|
||||
ave = (zEnd-zStart)/ave
|
||||
return ave
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# returns the volume and galaxy density for a given redshit slice
|
||||
def getSurveyProps(maskFile, zmin, zmax, selFunMin, selFunMax, portion, selectionFuncFile=None, useComoving=False):
|
||||
|
||||
LIGHT_SPEED = 299792.458
|
||||
|
||||
mask = healpy.read_map(maskFile)
|
||||
area = (1.*np.size(np.where(mask > 0)) / np.size(mask)) * 4.*np.pi
|
||||
|
||||
if useComoving:
|
||||
zmin = LIGHT_SPEED/100.*angularDiameter(zmin, Om=0.27)
|
||||
zmax = LIGHT_SPEED/100.*angularDiameter(zmax, Om=0.27)
|
||||
selFunMin = LIGHT_SPEED/100.*angularDiameter(selFunMin, Om=0.27)
|
||||
selFunMax = LIGHT_SPEED/100.*angularDiameter(selFunMax, Om=0.27)
|
||||
else:
|
||||
zmin = zmin * 3000
|
||||
zmax = zmax * 3000
|
||||
selFunMin *= 3000
|
||||
selFunMax *= 3000
|
||||
volume = area * (zmax**3 - zmin**3) / 3
|
||||
|
||||
if selectionFuncFile == None:
|
||||
nbar = 1.0
|
||||
|
||||
elif not os.access(selectionFuncFile, os.F_OK):
|
||||
print(" Warning, selection function file %s not found, using default of uniform selection." % selectionFuncFile)
|
||||
nbar = 1.0
|
||||
|
||||
else:
|
||||
selfunc = np.genfromtxt(selectionFuncFile)
|
||||
selfunc = np.array(selfunc)
|
||||
selfunc[:,0] = selfunc[:,0]/100.
|
||||
selfuncUnity = selfunc
|
||||
selfuncUnity[:,1] = 1.0
|
||||
selfuncMin = selfunc[0,0]
|
||||
selfuncMax = selfunc[-1,0]
|
||||
selfuncDx = selfunc[1,0] - selfunc[0,0]
|
||||
selfuncN = np.size(selfunc[:,0])
|
||||
|
||||
selFunMin = max(selFunMin, selfuncMin)
|
||||
selFunMax = min(selFunMax, selfuncMax)
|
||||
|
||||
|
||||
def f(z): return selfunc[np.ceil((z-selfuncMin)/selfuncDx), 1]*z**2
|
||||
def fTotal(z): return selfuncUnity[np.ceil((z-selfuncMin)/selfuncDx), 1]*z**2
|
||||
|
||||
zrange = np.linspace(selFunMin, selFunMax)
|
||||
|
||||
nbar = scipy.integrate.quad(f, selFunMin, selFunMax)
|
||||
nbar = nbar[0]
|
||||
|
||||
ntotal = scipy.integrate.quad(fTotal, 0.0, max(selfuncUnity[:,0]))
|
||||
ntotal = ntotal[0]
|
||||
|
||||
nbar = ntotal / area / nbar
|
||||
|
||||
|
||||
return (volume, nbar)
|
670
python_source/vide/backend/launchers.py
Normal file
670
python_source/vide/backend/launchers.py
Normal file
|
@ -0,0 +1,670 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/backend/launchers.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
# routines which communicate with individual data analysis portions -
|
||||
# they make the main script easier to read
|
||||
|
||||
import os
|
||||
import glob
|
||||
from . import classes
|
||||
import numpy as np
|
||||
import numpy.ma as ma
|
||||
import os
|
||||
import shutil
|
||||
import glob
|
||||
import subprocess
|
||||
import sys
|
||||
from pylab import figure
|
||||
from netCDF4 import Dataset
|
||||
from vide.backend.classes import *
|
||||
from vide.backend.cosmologyTools import *
|
||||
import pickle
|
||||
import vide.apTools as vp
|
||||
import scipy.interpolate as interpolate
|
||||
|
||||
NetCDFFile = Dataset
|
||||
ncFloat = 'f8' # Double precision
|
||||
|
||||
LIGHT_SPEED = 299792.458
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def launchPrep(sample, binPath, workDir=None, inputDataDir=None,
|
||||
zobovDir=None, figDir=None, logFile=None, useComoving=False,
|
||||
continueRun=None,regenerate=False):
|
||||
|
||||
if sample.dataType == "observation":
|
||||
sampleName = sample.fullName
|
||||
|
||||
if regenerate:
|
||||
inputParameterFlag = "inputParameter " + zobovDir+"/zobov_slice_"+sampleName+".par"
|
||||
outputFile = zobovDir+"/regenerated_zobov_slice_" + sampleName
|
||||
else:
|
||||
inputParameterFlag = ""
|
||||
outputFile = zobovDir+"/zobov_slice_" + sampleName
|
||||
|
||||
if sample.dataFile == "":
|
||||
datafile = inputDataDir+"/"+sampleName
|
||||
else:
|
||||
datafile = inputDataDir+"/"+sample.dataFile
|
||||
|
||||
maskFile = sample.maskFile
|
||||
|
||||
if useComoving:
|
||||
useComovingFlag = "useComoving"
|
||||
else:
|
||||
useComovingFlag = ""
|
||||
|
||||
conf="""
|
||||
catalog %s
|
||||
mask %s
|
||||
output %s
|
||||
params %s
|
||||
zMin %g
|
||||
zMax %g
|
||||
density_fake %g
|
||||
%s
|
||||
%s
|
||||
omegaM %g
|
||||
""" % (datafile, maskFile, outputFile,
|
||||
zobovDir+"/zobov_slice_"+sampleName+".par",
|
||||
sample.zBoundary[0], sample.zBoundary[1], sample.fakeDensity,
|
||||
useComovingFlag, inputParameterFlag, sample.omegaM)
|
||||
|
||||
parmFile = os.getcwd()+"/generate_"+sample.fullName+".par"
|
||||
|
||||
if regenerate or not (continueRun and jobSuccessful(logFile, "Done!\n")):
|
||||
with open(parmFile, mode="wt") as f:
|
||||
f.write(conf)
|
||||
arg1 = "--configFile=%s" % parmFile
|
||||
with open(logFile, 'wt') as log:
|
||||
subprocess.call([binPath, arg1], stdout=log, stderr=log)
|
||||
if jobSuccessful(logFile, "Done!\n"):
|
||||
print("done")
|
||||
else:
|
||||
print("FAILED!")
|
||||
exit(-1)
|
||||
|
||||
else:
|
||||
print("already done!")
|
||||
|
||||
if os.access(parmFile, os.F_OK): os.unlink(parmFile)
|
||||
|
||||
if os.access("contour_map.fits", os.F_OK):
|
||||
os.system("mv %s %s" % ("contour_map.fits", zobovDir))
|
||||
os.system("mv %s %s" % ("mask_map.fits", zobovDir))
|
||||
|
||||
if os.access("comoving_distance.txt", os.F_OK):
|
||||
os.system("mv %s %s" % ("comoving_distance.txt", zobovDir))
|
||||
|
||||
if os.access("mask_index.txt", os.F_OK):
|
||||
os.system("mv %s %s" % ("mask_index.txt", zobovDir))
|
||||
os.system("mv %s %s" % ("total_particles.txt", zobovDir))
|
||||
|
||||
if os.access("galaxies.txt", os.F_OK):
|
||||
os.system("mv %s %s" % ("galaxies.txt", zobovDir))
|
||||
os.system("mv %s %s" % ("mock_galaxies.txt", zobovDir))
|
||||
os.system("mv %s %s" % ("mock_boundary.txt", zobovDir))
|
||||
os.system("mv %s %s" % ("mock_sphere.txt", zobovDir))
|
||||
|
||||
else: # simulation
|
||||
sampleName = sample.fullName
|
||||
|
||||
datafile = inputDataDir+"/"+sample.dataFile
|
||||
|
||||
# check if the final subsampling is done
|
||||
lastSample = sample.subsample.split(', ')[-1]
|
||||
doneLine = "Done! %5.2e\n" % float(lastSample)
|
||||
if (continueRun and jobSuccessful(logFile, doneLine)):
|
||||
print("already done!")
|
||||
return
|
||||
|
||||
prevSubSample = -1
|
||||
firstSubSample = -1
|
||||
for thisSubSample in sample.subsample.split(', '):
|
||||
|
||||
if prevSubSample == -1:
|
||||
inputParameterFlag = ""
|
||||
outputFile = zobovDir+"/zobov_slice_" + sampleName + "_ss" + \
|
||||
thisSubSample
|
||||
keepFraction = float(thisSubSample)
|
||||
subSampleLine = "subsample %g" % keepFraction
|
||||
resubSampleLine = ""
|
||||
firstSubSample = keepFraction
|
||||
else:
|
||||
inputParameterFlag = "inputParameter " + zobovDir+"/zobov_slice_"+\
|
||||
sampleName+"_ss"+prevSubSample+".par"
|
||||
outputFile = zobovDir+"/zobov_slice_" + sampleName + "_ss" + \
|
||||
thisSubSample
|
||||
keepFraction = float(thisSubSample)/float(prevSubSample)
|
||||
subSampleLine = "subsample %s" % firstSubSample
|
||||
resubSampleLine = "resubsample %g" % keepFraction
|
||||
|
||||
includePecVelString = ""
|
||||
if sample.usePecVel: includePecVelString = "peculiarVelocities"
|
||||
|
||||
useLightConeString = ""
|
||||
if sample.useLightCone: useLightConeString = "cosmo"
|
||||
|
||||
if sample.dataFormat == "multidark" or sample.dataFormat == "random":
|
||||
dataFileLine = "multidark " + datafile
|
||||
elif sample.dataFormat == "gadget":
|
||||
dataFileLine = "gadget " + datafile
|
||||
elif sample.dataFormat == "gadget2":
|
||||
dataFileLine = "gadget2 " + datafile
|
||||
elif sample.dataFormat == "ahf":
|
||||
dataFileLine = "gadget " + datafile
|
||||
elif sample.dataFormat == "sdf":
|
||||
dataFileLine = "sdf " + datafile
|
||||
elif sample.dataFormat == "ramses":
|
||||
ramsesId = int(os.path.split(datafile)[1][-5:len(datafile)]) # picks out the particle file (should be the output_NNNNN, then extracts the output id "NNNNN" as an integer)
|
||||
dataFileLine = "ramses " + datafile + "/"
|
||||
else:
|
||||
raise ValueError("unknown dataFormat '%s'" % sample.dataFormat)
|
||||
|
||||
iX = float(sample.mySubvolume[0])
|
||||
iY = float(sample.mySubvolume[1])
|
||||
|
||||
xMin = iX/sample.numSubvolumes * sample.boxLen
|
||||
yMin = iY/sample.numSubvolumes * sample.boxLen
|
||||
xMax = (iX+1)/sample.numSubvolumes * sample.boxLen
|
||||
yMax = (iY+1)/sample.numSubvolumes * sample.boxLen
|
||||
|
||||
reshiftFlag = ""
|
||||
if not sample.shiftSimZ: reshiftFlag = "preReShift"
|
||||
|
||||
if sample.dataFormat == "ramses":
|
||||
ramsesIdLine = "ramsesId " + str(ramsesId)
|
||||
else:
|
||||
ramsesIdLine = ""
|
||||
|
||||
conf="""
|
||||
%s
|
||||
output %s
|
||||
outputParameter %s
|
||||
%s
|
||||
%s
|
||||
gadgetUnit %g
|
||||
%s
|
||||
rangeX_min %g
|
||||
rangeX_max %g
|
||||
rangeY_min %g
|
||||
rangeY_max %g
|
||||
rangeZ_min %g
|
||||
rangeZ_max %g
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
""" % (dataFileLine,
|
||||
outputFile,
|
||||
outputFile+".par",
|
||||
includePecVelString,
|
||||
useLightConeString,
|
||||
sample.dataUnit,
|
||||
ramsesIdLine,
|
||||
xMin, xMax, yMin, yMax,
|
||||
sample.zBoundaryMpc[0], sample.zBoundaryMpc[1],
|
||||
subSampleLine,resubSampleLine,inputParameterFlag,reshiftFlag)
|
||||
|
||||
parmFile = os.getcwd()+"/generate_"+sample.fullName+".par"
|
||||
|
||||
with open(parmFile, mode="wt") as f:
|
||||
f.write(conf)
|
||||
|
||||
if (prevSubSample == -1):
|
||||
cmd = "%s --configFile=%s" % (binPath,parmFile)
|
||||
log = open(logFile, 'w')
|
||||
else:
|
||||
cmd = "%s --configFile=%s" % (binPath,parmFile)
|
||||
log = open(logFile, 'a')
|
||||
arg1 = "--configFile=%s" % parmFile
|
||||
|
||||
|
||||
subprocess.call(cmd, stdout=log, stderr=log, shell=True)
|
||||
log.close()
|
||||
|
||||
# remove intermediate files
|
||||
if (prevSubSample != -1):
|
||||
os.unlink(zobovDir+"/zobov_slice_"+sampleName+"_ss"+prevSubSample+".par")
|
||||
os.unlink(zobovDir+"/zobov_slice_"+sampleName+"_ss"+prevSubSample)
|
||||
|
||||
doneLine = "Done! %5.2e\n" % keepFraction
|
||||
if not jobSuccessful(logFile, doneLine):
|
||||
print("FAILED!") ### dies here for now
|
||||
exit(-1)
|
||||
|
||||
prevSubSample = thisSubSample
|
||||
|
||||
if jobSuccessful(logFile, doneLine): print("done")
|
||||
|
||||
# place the final subsample
|
||||
os.system("mv %s %s" % (zobovDir+"/zobov_slice_"+sampleName+"_ss"+\
|
||||
prevSubSample, zobovDir+"/zobov_slice_"+sampleName))
|
||||
os.system("mv %s %s" % (zobovDir+"/zobov_slice_"+sampleName+"_ss"+\
|
||||
prevSubSample+".par", zobovDir+"/zobov_slice_"+sampleName+".par"))
|
||||
|
||||
if os.access("comoving_distance.txt", os.F_OK):
|
||||
os.system("mv %s %s" % ("comoving_distance.txt", zobovDir))
|
||||
|
||||
if os.access(parmFile, os.F_OK):
|
||||
os.unlink(parmFile)
|
||||
|
||||
if os.access("mask_index.txt", os.F_OK):
|
||||
os.system("mv %s %s" % ("mask_index.txt", zobovDir))
|
||||
os.system("mv %s %s" % ("total_particles.txt", zobovDir))
|
||||
#os.system("mv %s %s" % ("sample_info.txt", zobovDir))
|
||||
|
||||
# add to sample info file
|
||||
if sample.dataType == "observation":
|
||||
(boxVol, nbar) = vp.getSurveyProps(sample.maskFile, sample.zRange[0],
|
||||
sample.zRange[1], sample.zRange[0], sample.zRange[1], "all",
|
||||
useComoving=useComoving)
|
||||
else:
|
||||
iX = float(sample.mySubvolume[0])
|
||||
iY = float(sample.mySubvolume[1])
|
||||
xMin = iX/sample.numSubvolumes * sample.boxLen
|
||||
yMin = iY/sample.numSubvolumes * sample.boxLen
|
||||
xMax = (iX+1)/sample.numSubvolumes * sample.boxLen
|
||||
yMax = (iY+1)/sample.numSubvolumes * sample.boxLen
|
||||
zMin = sample.zBoundaryMpc[0]
|
||||
zMax = sample.zBoundaryMpc[1]
|
||||
|
||||
boxVol = (xMax-xMin)*(yMax-yMin)*(zMax-zMin)
|
||||
nbar = 1.0
|
||||
|
||||
numTracers = int(open(zobovDir+"/mask_index.txt", "r").read())
|
||||
numTotal = int(open(zobovDir+"/total_particles.txt", "r").read())
|
||||
|
||||
meanSep = (1.*numTracers/boxVol/nbar)**(-1/3.)
|
||||
|
||||
# save this sample's information
|
||||
with open(zobovDir+"/sample_info.dat", mode='wb') as output:
|
||||
pickle.dump(sample, output, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
fp = open(zobovDir+"/sample_info.txt", 'w')
|
||||
fp.write("Sample name: %s\n" % sample.fullName)
|
||||
fp.write("Sample nickname: %s\n" % sample.nickName)
|
||||
fp.write("Data type: %s\n" % sample.dataType)
|
||||
fp.write("Redshift range: %f - %f\n" %(sample.zBoundary[0],sample.zBoundary[1]))
|
||||
if (sample.dataType == "simulation"):
|
||||
fp.write("Particles placed on lightcone: %g\n" % sample.useLightCone)
|
||||
fp.write("Peculiar velocities included: %g\n" % sample.usePecVel)
|
||||
if (len(sample.subsample) == 1):
|
||||
fp.write("Additional subsampling fraction: %s\n" % sample.subsample)
|
||||
else:
|
||||
fp.write("Additional subsampling fraction: %s\n" % sample.subsample[-1])
|
||||
fp.write("Simulation box length (Mpc/h): %g\n" % sample.boxLen)
|
||||
fp.write("Simulation Omega_M: %g\n" % sample.omegaM)
|
||||
fp.write("Number of simulation subvolumes: %s\n" % sample.numSubvolumes)
|
||||
fp.write("My subvolume index: %s\n" % sample.mySubvolume)
|
||||
fp.write("Estimated volume (cubic Mpc/h): %g\n" % boxVol)
|
||||
fp.write("Number of real (non-boundary) tracers: %d\n" % numTracers)
|
||||
fp.write("Total number of tracers: %d\n" % numTotal)
|
||||
fp.write("Estimated mean tracer separation (Mpc/h): %g\n" % meanSep)
|
||||
fp.write("Minimum void size actually used (Mpc/h): %g\n" % sample.minVoidRadius)
|
||||
fp.close()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def launchZobov(sample, binPath, zobovDir=None, logDir=None, continueRun=None,
|
||||
numZobovDivisions=None, numZobovThreads=None, mergingThreshold=0.2):
|
||||
|
||||
sampleName = sample.fullName
|
||||
|
||||
datafile = zobovDir+"zobov_slice_"+sampleName
|
||||
|
||||
logFile = logDir+"/zobov_"+sampleName+".out"
|
||||
|
||||
vozScript = "./scr_"+sampleName
|
||||
|
||||
if os.access(vozScript, os.F_OK):
|
||||
os.unlink(vozScript)
|
||||
|
||||
if sample.dataType == "observation":
|
||||
maskIndex = open(zobovDir+"/mask_index.txt", "r").read()
|
||||
totalPart = open(zobovDir+"/total_particles.txt", "r").read()
|
||||
maxDen = mergingThreshold*float(maskIndex)/float(totalPart)
|
||||
else:
|
||||
maskIndex = -1
|
||||
maxDen = mergingThreshold
|
||||
if numZobovDivisions == 1:
|
||||
print(" WARNING! You are using a single ZOBOV division with a simulation. Periodic boundaries will not be respected!")
|
||||
|
||||
if not (continueRun and jobSuccessful(logFile, "Done!\n")):
|
||||
for fileName in glob.glob(zobovDir+"/part._"+sampleName+".*"):
|
||||
os.unlink(fileName)
|
||||
|
||||
if os.access(zobovDir+"/adj_"+sampleName+".dat", os.F_OK):
|
||||
os.unlink(zobovDir+"adj_"+sampleName+".dat")
|
||||
|
||||
if os.access(zobovDir+"/voidDesc_"+sampleName+".out", os.F_OK):
|
||||
os.unlink(zobovDir+"/voidDesc_"+sampleName+".out")
|
||||
|
||||
cmd = [binPath+"/vozinit", datafile, "0.1", "1.0", str(numZobovDivisions), \
|
||||
"_"+sampleName, str(numZobovThreads), \
|
||||
binPath, zobovDir, str(maskIndex)]
|
||||
log = open(logFile, 'w')
|
||||
subprocess.call(cmd, stdout=log, stderr=log)
|
||||
log.close()
|
||||
|
||||
cmd = ["./%s" % vozScript]
|
||||
log = open(logFile, 'a')
|
||||
subprocess.call(cmd, stdout=log, stderr=log)
|
||||
log.close()
|
||||
|
||||
# re-weight the volumes based on selection function
|
||||
if sample.dataType == "observation" and \
|
||||
sample.selFunFile != None:
|
||||
|
||||
# load volumes
|
||||
volFile = zobovDir+"/vol_"+sampleName+".dat"
|
||||
with open(volFile, mode="rb") as File:
|
||||
numPartTot = np.fromfile(File, dtype=np.int32,count=1)
|
||||
vols = np.fromfile(File, dtype=np.float32,count=numPartTot)
|
||||
|
||||
# load redshifts
|
||||
partFile = zobovDir+"/zobov_slice_"+sample.fullName
|
||||
with open(partFile, mode="rb") as File:
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
Np = np.fromfile(File, dtype=np.int32,count=1)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
# x
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
redshifts = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
# y
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
redshifts = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
# z
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
redshifts = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
# RA
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
redshifts = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
# Dec
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
redshifts = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
# z
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
redshifts = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
# build selection function interpolation
|
||||
selfuncData = np.genfromtxt(sample.selFunFile)
|
||||
selfunc = interpolate.interp1d(selfuncData[:,0], selfuncData[:,1],
|
||||
kind='cubic', bounds_error=False,
|
||||
fill_value=1.0)
|
||||
# re-weight and write
|
||||
## TEST
|
||||
#redshifts /= 10000.
|
||||
for i in range(len(vols)):
|
||||
vols[i] *= selfunc(redshifts[i])
|
||||
|
||||
volFile = zobovDir+"/vol_weighted_"+sampleName+".dat"
|
||||
with open(volFile, mode='wb') as File:
|
||||
numPartTot.astype(np.int32).tofile(File)
|
||||
vols.astype(np.float32).tofile(File)
|
||||
|
||||
volFileToUse = zobovDir+"/vol_weighted_"+sampleName+".dat"
|
||||
else:
|
||||
volFileToUse = zobovDir+"/vol_"+sampleName+".dat"
|
||||
|
||||
|
||||
cmd = [binPath+"/jozov2", \
|
||||
zobovDir+"/adj_"+sampleName+".dat", \
|
||||
volFileToUse, \
|
||||
zobovDir+"/voidPart_"+sampleName+".dat", \
|
||||
zobovDir+"/voidZone_"+sampleName+".dat", \
|
||||
zobovDir+"/voidDesc_"+sampleName+".out", \
|
||||
str(maxDen), str(maskIndex)]
|
||||
log = open(logFile, 'a')
|
||||
subprocess.call(cmd, stdout=log, stderr=log)
|
||||
log.close()
|
||||
|
||||
# don't need the subbox files
|
||||
for fileName in glob.glob(zobovDir+"/part._"+sampleName+".*"):
|
||||
os.unlink(fileName)
|
||||
|
||||
if jobSuccessful(logFile, "Done!\n"):
|
||||
print("done")
|
||||
else:
|
||||
print("FAILED!")
|
||||
exit(-1)
|
||||
|
||||
else:
|
||||
print("already done!")
|
||||
|
||||
if os.access(vozScript, os.F_OK):
|
||||
os.unlink(vozScript)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def launchPrune(sample, binPath,
|
||||
summaryFile=None, logFile=None, zobovDir=None,
|
||||
continueRun=None, useComoving=False, mergingThreshold=0.2):
|
||||
|
||||
sampleName = sample.fullName
|
||||
|
||||
numVoids = sum(1 for line in \
|
||||
open(zobovDir+"/voidDesc_"+sampleName+".out"))
|
||||
numVoids -= 2
|
||||
|
||||
if sample.dataType == "observation":
|
||||
mockIndex = open(zobovDir+"/mask_index.txt", "r").read()
|
||||
totalPart = open(zobovDir+"/total_particles.txt", "r").read()
|
||||
maxDen = mergingThreshold*float(mockIndex)/float(totalPart)
|
||||
observationLine = " --isObservation"
|
||||
#periodicLine = " --periodic=''"
|
||||
else:
|
||||
mockIndex = -1
|
||||
maxDen = mergingThreshold
|
||||
observationLine = ""
|
||||
|
||||
periodicLine = " --periodic='" + getPeriodic(sample) + "'"
|
||||
|
||||
if useComoving:
|
||||
useComovingFlag = " --useComoving"
|
||||
else:
|
||||
useComovingFlag = ""
|
||||
|
||||
if sample.minVoidRadius == -1:
|
||||
minRadius = -1
|
||||
for line in open(zobovDir+"/sample_info.txt"):
|
||||
if "Estimated mean tracer separation" in line:
|
||||
minRadius = float(line.split()[5])
|
||||
break
|
||||
if minRadius == -1:
|
||||
print("Could not grab mean tracer separation!?")
|
||||
exit(-1)
|
||||
else:
|
||||
minRadius = sample.minVoidRadius
|
||||
|
||||
if not (continueRun and (jobSuccessful(logFile, "NetCDF: Not a valid ID\n") \
|
||||
or jobSuccessful(logFile, "Done!\n"))):
|
||||
cmd = binPath
|
||||
cmd += " --partFile=" + zobovDir+"/zobov_slice_"+str(sampleName)
|
||||
cmd += " --voidDesc=" + zobovDir+"/voidDesc_"+str(sampleName)+".out"
|
||||
cmd += " --void2Zone="+zobovDir+"/voidZone_"+str(sampleName)+".dat"
|
||||
cmd += " --zone2Part=" + zobovDir+"/voidPart_"+str(sampleName)+".dat"
|
||||
cmd += " --partVol=" + zobovDir+"/vol_"+str(sampleName)+".dat"
|
||||
cmd += " --partAdj=" + zobovDir+"/adj_"+str(sampleName)+".dat"
|
||||
cmd += " --extraInfo=" + zobovDir+"/zobov_slice_"+str(sampleName)+\
|
||||
".par"
|
||||
cmd += " --tolerance=1.0"
|
||||
cmd += " --mockIndex=" + str(mockIndex)
|
||||
cmd += " --maxCentralDen=" + str(maxDen)
|
||||
cmd += " --zMin=" + str(sample.zRange[0])
|
||||
cmd += " --zMax=" + str(sample.zRange[1])
|
||||
cmd += " --rMin=" + str(minRadius)
|
||||
cmd += " --numVoids=" + str(numVoids)
|
||||
cmd += observationLine
|
||||
cmd += periodicLine
|
||||
cmd += useComovingFlag
|
||||
cmd += " --omegaM=" + str(sample.omegaM)
|
||||
cmd += " --outputDir=" + zobovDir
|
||||
cmd += " --sampleName=" + str(sampleName)
|
||||
log = open(logFile, 'w')
|
||||
log.write(f"Command is {cmd}\n")
|
||||
subprocess.call(cmd, stdout=log, stderr=log, shell=True)
|
||||
log.close()
|
||||
|
||||
if jobSuccessful(logFile, "NetCDF: Not a valid ID\n") or \
|
||||
jobSuccessful(logFile, "Done!\n"):
|
||||
print("done")
|
||||
else:
|
||||
print("FAILED!")
|
||||
#exit(-1)
|
||||
|
||||
else:
|
||||
print("already done!")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def launchVoidOverlap(sample1, sample2, sample1Dir, sample2Dir,
|
||||
binPath, thisDataPortion=None,
|
||||
logFile=None,
|
||||
continueRun=None, outputFile=None,
|
||||
overlapFrac=0.25,
|
||||
matchMethod=None, strictMatch=False):
|
||||
|
||||
sampleName1 = sample1.fullName
|
||||
sampleName2 = sample2.fullName
|
||||
|
||||
periodicLine = " --periodic='" + getPeriodic(sample1) + "' "
|
||||
|
||||
if strictMatch:
|
||||
matchPrefix = ""
|
||||
else:
|
||||
matchPrefix = "trimmed_nodencut_"
|
||||
|
||||
if sample1.dataType == "observation" or sample2.dataType == "observation":
|
||||
observationLine = " --isObservation"
|
||||
else:
|
||||
observationLine = ""
|
||||
|
||||
if not (continueRun and jobSuccessful(logFile, "Done!\n")):
|
||||
cmd = binPath
|
||||
cmd += " --partFile1=" + sample1Dir+"/zobov_slice_" + \
|
||||
str(sampleName1)
|
||||
cmd += " --volFile1=" + sample1Dir+"/vol_" + \
|
||||
str(sampleName1)+".dat"
|
||||
cmd += " --voidFile1=" + sample1Dir+"/voidDesc_" + \
|
||||
thisDataPortion+"_"+str(sampleName1)+".out"
|
||||
cmd += " --infoFile1=" + sample1Dir+"/zobov_slice_" + \
|
||||
str(sampleName1)+".par"
|
||||
cmd += " --centerFile1=" + sample1Dir + \
|
||||
"/macrocenters_"+thisDataPortion+"_"+str(sampleName1)+".out"
|
||||
cmd += " --shapeFile1=" + sample1Dir + \
|
||||
"/shapes_"+thisDataPortion+"_"+str(sampleName1)+".out"
|
||||
cmd += " --zoneFile1=" + sample1Dir+"/voidZone_" + \
|
||||
str(sampleName1)+".dat"
|
||||
cmd += " --zonePartFile1=" + sample1Dir+"/voidPart_" + \
|
||||
str(sampleName1)+".dat"
|
||||
|
||||
cmd += " --partFile2=" + sample2Dir+"/zobov_slice_" + \
|
||||
str(sampleName2)
|
||||
cmd += " --volFile2=" + sample2Dir+"/vol_" + \
|
||||
str(sampleName2)+".dat"
|
||||
cmd += " --voidFile2=" + sample2Dir+"/"+matchPrefix+"voidDesc_" + \
|
||||
thisDataPortion+"_"+str(sampleName2)+".out"
|
||||
cmd += " --infoFile2=" + sample2Dir+"/zobov_slice_" + \
|
||||
str(sampleName2)+".par"
|
||||
cmd += " --centerFile2=" + sample2Dir + \
|
||||
"/"+matchPrefix+"macrocenters_"+thisDataPortion+"_"+str(sampleName2)+".out"
|
||||
cmd += " --shapeFile2=" + sample2Dir + \
|
||||
"/"+matchPrefix+"shapes_"+thisDataPortion+"_"+str(sampleName2)+".out"
|
||||
cmd += " --zoneFile2=" + sample2Dir+"/voidZone_" + \
|
||||
str(sampleName2)+".dat"
|
||||
cmd += " --zonePartFile2=" + sample2Dir+"/voidPart_" + \
|
||||
str(sampleName2)+".dat"
|
||||
|
||||
cmd += " --overlapFrac=" + str(overlapFrac)
|
||||
|
||||
cmd += observationLine
|
||||
|
||||
if matchMethod == "useID": cmd += " --useID"
|
||||
cmd += periodicLine
|
||||
cmd += " --outfile=" + outputFile
|
||||
#cmd += " &> " + logFile
|
||||
#open("temp.par",'w').write(cmd)
|
||||
#os.system(cmd)
|
||||
log = open(logFile, 'w')
|
||||
subprocess.call(cmd, stdout=log, stderr=log, shell=True)
|
||||
log.close()
|
||||
|
||||
#if jobSuccessful(logFile, "Done!\n"):
|
||||
print("done")
|
||||
#else:
|
||||
# print "FAILED!"
|
||||
# exit(-1)
|
||||
|
||||
else:
|
||||
print("already done!")
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def launchVelocityStack(sample, stack, binPath,
|
||||
velField_file,
|
||||
thisDataPortion=None, logDir=None,
|
||||
voidDir=None, runSuffix=None,
|
||||
zobovDir=None,
|
||||
summaryFile=None,
|
||||
continueRun=None, dataType=None, prefixRun=""):
|
||||
|
||||
sampleName = sample.fullName
|
||||
|
||||
runSuffix = getStackSuffix(stack.zMin, stack.zMax, stack.rMin,
|
||||
stack.rMax, thisDataPortion)
|
||||
|
||||
logFile = logDir+("/%svelocity_stack_"%prefixRun)+sampleName+"_"+runSuffix+".out"
|
||||
|
||||
voidCenters=voidDir+"/centers.txt"
|
||||
# Rmax =
|
||||
|
||||
centralRadius = stack.rMin * 0.25
|
||||
Rextracut = stack.rMax*3 + 1
|
||||
Rcircular = stack.rMax*3 + 2
|
||||
|
||||
parameters="--velocityField=%s --voidCenters=%s --Rmax=%e --L0=%e --numBins=%d" % (velField_file, voidCenters, Rmax, Boxsize, numBins)
|
||||
|
||||
if not (continueRun and jobSuccessful(logFile, "Done!\n")):
|
||||
#cmd = "%s %s &> %s" % (binPath,parameters,logFile)
|
||||
#os.system(cmd)
|
||||
cmd = "%s %s" % (binPath,parameters)
|
||||
log = open(logFile, 'w')
|
||||
subprocess.call(cmd, stdout=log, stderr=log, shell=True)
|
||||
log.close()
|
||||
if jobSuccessful(logFile, "Done!\n"):
|
||||
print("done")
|
||||
else:
|
||||
print("FAILED!")
|
||||
exit(-1)
|
||||
|
||||
else:
|
||||
print("already done!")
|
26
python_source/vide/voidUtil/__init__.py
Normal file
26
python_source/vide/voidUtil/__init__.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/voidUtil/__init__.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
|
||||
from .catalogUtil import *
|
||||
from .plotDefs import *
|
||||
from .plotUtil import *
|
||||
from .matchUtil import *
|
||||
from .xcorUtil import *
|
||||
from .profileUtil import *
|
586
python_source/vide/voidUtil/catalogUtil.py
Normal file
586
python_source/vide/voidUtil/catalogUtil.py
Normal file
|
@ -0,0 +1,586 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/voidUtil/catalogUtil.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
|
||||
# Various utilities for loading and modifying particle datasets
|
||||
|
||||
import numpy as np
|
||||
from netCDF4 import Dataset
|
||||
import sys
|
||||
from vide.backend import *
|
||||
import vide.apTools as vp
|
||||
import pickle
|
||||
from .periodic_kdtree import PeriodicCKDTree
|
||||
import os
|
||||
|
||||
NetCDFFile = Dataset
|
||||
ncFloat = 'f8'
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def loadPart(sampleDir):
|
||||
print(" Loading particle data...")
|
||||
sys.stdout.flush()
|
||||
|
||||
with open(sampleDir+"/sample_info.dat", 'rb') as input:
|
||||
sample = pickle.load(input)
|
||||
|
||||
infoFile = sampleDir+"/zobov_slice_"+sample.fullName+".par"
|
||||
File = NetCDFFile(infoFile, 'r')
|
||||
ranges = np.zeros((3,2))
|
||||
ranges[0][0] = getattr(File, 'range_x_min')
|
||||
ranges[0][1] = getattr(File, 'range_x_max')
|
||||
ranges[1][0] = getattr(File, 'range_y_min')
|
||||
ranges[1][1] = getattr(File, 'range_y_max')
|
||||
ranges[2][0] = getattr(File, 'range_z_min')
|
||||
ranges[2][1] = getattr(File, 'range_z_max')
|
||||
isObservation = getattr(File, 'is_observation')
|
||||
maskIndex = getattr(File, 'mask_index')
|
||||
File.close()
|
||||
mul = np.zeros((3))
|
||||
mul[:] = ranges[:,1] - ranges[:,0]
|
||||
|
||||
partFile = sampleDir+"/zobov_slice_"+sample.fullName
|
||||
iLine = 0
|
||||
partData = []
|
||||
part = np.zeros((3))
|
||||
with open(partFile, mode="rb") as File:
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
Np = np.fromfile(File, dtype=np.int32,count=1)[0]
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
x = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
x *= mul[0]
|
||||
if isObservation != 1:
|
||||
x += ranges[0][0]
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
y = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
y *= mul[1]
|
||||
if isObservation != 1:
|
||||
y += ranges[1][0]
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
z = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
z *= mul[2]
|
||||
if isObservation != 1:
|
||||
z += ranges[2][0]
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
RA = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
Dec = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
redshift = np.fromfile(File, dtype=np.float32,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
uniqueID = np.fromfile(File, dtype=np.int64,count=Np)
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
|
||||
if isObservation == 1:
|
||||
x = x[0:maskIndex]# * 100/300000
|
||||
y = y[0:maskIndex]# * 100/300000
|
||||
z = z[0:maskIndex]# * 100/300000
|
||||
RA = RA[0:maskIndex]
|
||||
Dec = Dec[0:maskIndex]
|
||||
redshift = redshift[0:maskIndex]
|
||||
uniqueID = uniqueID[0:maskIndex]
|
||||
|
||||
partData = np.column_stack((x,y,z))
|
||||
|
||||
extraData = np.column_stack((RA,Dec,redshift,uniqueID))
|
||||
|
||||
boxLen = mul
|
||||
|
||||
#if isObservation == 1:
|
||||
# # look for the mask file
|
||||
# if os.access(sample.maskFile, os.F_OK):
|
||||
# maskFile = sample.maskFile
|
||||
# else:
|
||||
# maskFile = sampleDir+"/"+os.path.basename(sample.maskFile)
|
||||
# print "Using maskfile found in:", maskFile
|
||||
# props = vp.getSurveyProps(maskFile, sample.zBoundary[0],
|
||||
# sample.zBoundary[1],
|
||||
# sample.zBoundary[0],
|
||||
# sample.zBoundary[1], "all",
|
||||
# selectionFuncFile=sample.selFunFile,
|
||||
# useComoving=sample.useComoving)
|
||||
# boxVol = props[0]
|
||||
# volNorm = maskIndex/boxVol
|
||||
#else:
|
||||
boxVol = np.prod(boxLen)
|
||||
volNorm = len(x)/boxVol
|
||||
|
||||
isObservationData = isObservation == 1
|
||||
|
||||
return partData, boxLen, volNorm, isObservationData, ranges, extraData
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def getVolNorm(sampleDir):
|
||||
with open(sampleDir+"/sample_info.dat", 'rb') as input:
|
||||
sample = pickle.load(input)
|
||||
|
||||
infoFile = sampleDir+"/zobov_slice_"+sample.fullName+".par"
|
||||
File = NetCDFFile(infoFile, 'r')
|
||||
ranges = np.zeros((3,2))
|
||||
ranges[0][0] = getattr(File, 'range_x_min')
|
||||
ranges[0][1] = getattr(File, 'range_x_max')
|
||||
ranges[1][0] = getattr(File, 'range_y_min')
|
||||
ranges[1][1] = getattr(File, 'range_y_max')
|
||||
ranges[2][0] = getattr(File, 'range_z_min')
|
||||
ranges[2][1] = getattr(File, 'range_z_max')
|
||||
isObservation = getattr(File, 'is_observation')
|
||||
maskIndex = getattr(File, 'mask_index')
|
||||
File.close()
|
||||
mul = np.zeros((3))
|
||||
mul[:] = ranges[:,1] - ranges[:,0]
|
||||
|
||||
partFile = sampleDir+"/zobov_slice_"+sample.fullName
|
||||
with open(partFile, mode="rb") as File:
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
Np = np.fromfile(File, dtype=np.int32,count=1)[0]
|
||||
|
||||
boxLen = mul
|
||||
|
||||
#if isObservation == 1:
|
||||
# # look for the mask file
|
||||
# if os.access(sample.maskFile, os.F_OK):
|
||||
# maskFile = sample.maskFile
|
||||
# else:
|
||||
# maskFile = sampleDir+"/"+os.path.basename(sample.maskFile)
|
||||
# print "Using maskfile found in:", maskFile
|
||||
# props = vp.getSurveyProps(maskFile, sample.zBoundary[0],
|
||||
# sample.zBoundary[1],
|
||||
# sample.zBoundary[0],
|
||||
# sample.zBoundary[1], "all",
|
||||
# selectionFuncFile=sample.selFunFile,
|
||||
# useComoving=sample.useComoving)
|
||||
# boxVol = props[0]
|
||||
# volNorm = maskIndex/boxVol
|
||||
#else:
|
||||
boxVol = np.prod(boxLen)
|
||||
volNorm = Np/boxVol
|
||||
|
||||
return volNorm
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def loadPartVel(sampleDir):
|
||||
#print " Loading particle velocities..."
|
||||
sys.stdout.flush()
|
||||
|
||||
with open(sampleDir+"/sample_info.dat", 'rb') as input:
|
||||
sample = pickle.load(input)
|
||||
|
||||
infoFile = sampleDir+"/zobov_slice_"+sample.fullName+".par"
|
||||
File = NetCDFFile(infoFile, 'r')
|
||||
isObservation = getattr(File, 'is_observation')
|
||||
|
||||
if isObservation:
|
||||
print("No velocities for observations!")
|
||||
return -1
|
||||
|
||||
vx = File.variables['vel_x'][0:]
|
||||
vy = File.variables['vel_y'][0:]
|
||||
vz = File.variables['vel_z'][0:]
|
||||
|
||||
File.close()
|
||||
|
||||
partVel = np.column_stack((vx,vy,vz))
|
||||
|
||||
return partVel
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def getPartTree(catalog):
|
||||
|
||||
sample = catalog.sampleInfo
|
||||
partData = catalog.partPos
|
||||
boxLen = catalog.boxLen
|
||||
|
||||
periodicLine = getPeriodic(sample)
|
||||
|
||||
periodic = 1.*boxLen
|
||||
|
||||
if not "x" in periodicLine: periodic[0] = -1
|
||||
if not "y" in periodicLine: periodic[1] = -1
|
||||
if not "z" in periodicLine: periodic[2] = -1
|
||||
|
||||
return PeriodicCKDTree(periodic, partData)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def getBall(partTree, center, radius):
|
||||
|
||||
return partTree.query_ball_point(center, r=radius)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def shiftPart(inPart, center, periodicLine, ranges):
|
||||
|
||||
part = inPart.copy()
|
||||
newCenter = 1.*center;
|
||||
|
||||
boxLen = np.zeros((3))
|
||||
boxLen[0] = ranges[0][1] - ranges[0][0]
|
||||
boxLen[1] = ranges[1][1] - ranges[1][0]
|
||||
boxLen[2] = ranges[2][1] - ranges[2][0]
|
||||
|
||||
# shift to box coordinates
|
||||
part[:,0] -= ranges[0][0]
|
||||
part[:,1] -= ranges[1][0]
|
||||
part[:,2] -= ranges[2][0]
|
||||
|
||||
newCenter[:] -= ranges[:,0]
|
||||
|
||||
part[:,0] -= newCenter[0]
|
||||
part[:,1] -= newCenter[1]
|
||||
part[:,2] -= newCenter[2]
|
||||
|
||||
shiftUs = np.abs(part[:,0]) > boxLen[0]/2.
|
||||
if ("x" in periodicLine): part[shiftUs,0] -= \
|
||||
np.copysign(boxLen[0], part[shiftUs,0])
|
||||
shiftUs = np.abs(part[:,1]) > boxLen[1]/2.
|
||||
if ("y" in periodicLine): part[shiftUs,1] -= \
|
||||
np.copysign(boxLen[1], part[shiftUs,1])
|
||||
shiftUs = np.abs(part[:,2]) > boxLen[2]/2.
|
||||
if ("z" in periodicLine): part[shiftUs,2] -= \
|
||||
np.copysign(boxLen[2], part[shiftUs,2])
|
||||
|
||||
|
||||
#part[:,0] += ranges[0][0]
|
||||
#part[:,1] += ranges[1][0]
|
||||
#part[:,2] += ranges[2][0]
|
||||
|
||||
return part
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
class Bunch:
|
||||
def __init__(self, **kwds):
|
||||
self.__dict__.update(kwds)
|
||||
|
||||
class Catalog:
|
||||
numVoids = 0
|
||||
numPartTot = 0
|
||||
numZonesTot = 0
|
||||
volNorm = 0
|
||||
boxLen = np.zeros((3))
|
||||
ranges = np.zeros((3,2))
|
||||
part = None
|
||||
zones2Parts = None
|
||||
void2Zones = None
|
||||
voids = None
|
||||
sampleInfo = None
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def loadVoidCatalog(sampleDir, dataPortion="central", loadParticles=True,
|
||||
untrimmed=False):
|
||||
|
||||
# loads a void catalog
|
||||
# by default, loads parent-level voids with central densities greater than 0.2*mean
|
||||
# sampleDir: path to VIDE output directory
|
||||
# dataPortion: "central" or "all"
|
||||
# loadParticles: if True, also load particle information
|
||||
# untrimmed: if True, catalog contains all voids, regardless of density or hierarchy level
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
catalog = Catalog()
|
||||
with open(sampleDir+"/sample_info.dat", 'rb') as input:
|
||||
sample = pickle.load(input)
|
||||
catalog.sampleInfo = sample
|
||||
|
||||
print("Loading info...")
|
||||
infoFile = sampleDir+"/zobov_slice_"+sample.fullName+".par"
|
||||
File = NetCDFFile(infoFile, 'r')
|
||||
ranges = np.zeros((3,2))
|
||||
ranges[0][0] = getattr(File, 'range_x_min')
|
||||
ranges[0][1] = getattr(File, 'range_x_max')
|
||||
ranges[1][0] = getattr(File, 'range_y_min')
|
||||
ranges[1][1] = getattr(File, 'range_y_max')
|
||||
ranges[2][0] = getattr(File, 'range_z_min')
|
||||
ranges[2][1] = getattr(File, 'range_z_max')
|
||||
catalog.boxLen[0] = ranges[0][1] - ranges[0][0]
|
||||
catalog.boxLen[1] = ranges[1][1] - ranges[1][0]
|
||||
catalog.boxLen[2] = ranges[2][1] - ranges[2][0]
|
||||
catalog.ranges = ranges
|
||||
File.close()
|
||||
|
||||
volNorm = getVolNorm(sampleDir)
|
||||
catalog.volNorm = volNorm
|
||||
|
||||
if untrimmed:
|
||||
prefix = "untrimmed_"
|
||||
else:
|
||||
prefix = ""
|
||||
|
||||
print("Loading voids...")
|
||||
fileName = sampleDir+"/"+prefix+"voidDesc_"+dataPortion+"_"+sample.fullName+".out"
|
||||
catData = np.loadtxt(fileName, comments="#", skiprows=2)
|
||||
catalog.voids = []
|
||||
for line in catData:
|
||||
catalog.voids.append(Bunch(iVoid = int(line[0]),
|
||||
voidID = int(line[1]),
|
||||
coreParticle = line[2],
|
||||
coreDens = line[3],
|
||||
zoneVol = line[4],
|
||||
zoneNumPart = line[5],
|
||||
numZones = int(line[6]),
|
||||
voidVol = line[7],
|
||||
numPart = int(line[8]),
|
||||
densCon = line[9],
|
||||
voidProb = line[10],
|
||||
radius = 0., # this is read in later
|
||||
macrocenter = np.zeros((3)),
|
||||
redshift = 0,
|
||||
RA = 0,
|
||||
Dec = 0,
|
||||
parentID = 0,
|
||||
treeLevel = 0,
|
||||
numChildren = 0,
|
||||
centralDen = 0.,
|
||||
ellipticity = 0.,
|
||||
eigenVals = np.zeros((3)),
|
||||
eigenVecs = np.zeros((3,3)),
|
||||
))
|
||||
|
||||
catalog.numVoids = len(catalog.voids)
|
||||
print("Read %d voids" % catalog.numVoids)
|
||||
|
||||
print("Loading macrocenters...")
|
||||
iLine = 0
|
||||
for line in open(sampleDir+"/"+prefix+"macrocenters_"+dataPortion+"_"+sample.fullName+".out"):
|
||||
line = line.split()
|
||||
catalog.voids[iLine].macrocenter[0] = float(line[1])
|
||||
catalog.voids[iLine].macrocenter[1] = float(line[2])
|
||||
catalog.voids[iLine].macrocenter[2] = float(line[3])
|
||||
iLine += 1
|
||||
|
||||
iLine = 0
|
||||
fileName = sampleDir+"/"+prefix+"sky_positions_"+dataPortion+"_"+sample.fullName+".out"
|
||||
catData = np.loadtxt(fileName, comments="#")
|
||||
for line in catData:
|
||||
catalog.voids[iLine].RA = float(line[0])
|
||||
catalog.voids[iLine].Dec = float(line[1])
|
||||
iLine += 1
|
||||
|
||||
|
||||
print("Loading derived void information...")
|
||||
fileName = sampleDir+"/"+prefix+"centers_"+dataPortion+"_"+sample.fullName+".out"
|
||||
catData = np.loadtxt(fileName, comments="#")
|
||||
for (iLine,line) in enumerate(catData):
|
||||
catalog.voids[iLine].volume = float(line[6])
|
||||
catalog.voids[iLine].radius = float(line[4])
|
||||
catalog.voids[iLine].redshift = float(line[5])
|
||||
catalog.voids[iLine].parentID = float(line[10])
|
||||
catalog.voids[iLine].treeLevel = float(line[11])
|
||||
catalog.voids[iLine].numChildren = float(line[12])
|
||||
catalog.voids[iLine].centralDen = float(line[13])
|
||||
iLine += 1
|
||||
|
||||
fileName = sampleDir+"/"+prefix+"shapes_"+dataPortion+"_"+sample.fullName+".out"
|
||||
catData = np.loadtxt(fileName, comments="#")
|
||||
for (iLine,line) in enumerate(catData):
|
||||
catalog.voids[iLine].ellipticity = float(line[1])
|
||||
|
||||
catalog.voids[iLine].eigenVals[0] = float(line[2])
|
||||
catalog.voids[iLine].eigenVals[1] = float(line[3])
|
||||
catalog.voids[iLine].eigenVals[2] = float(line[4])
|
||||
|
||||
catalog.voids[iLine].eigenVecs[0][0] = float(line[5])
|
||||
catalog.voids[iLine].eigenVecs[0][1] = float(line[6])
|
||||
catalog.voids[iLine].eigenVecs[0][2] = float(line[7])
|
||||
|
||||
catalog.voids[iLine].eigenVecs[1][0] = float(line[8])
|
||||
catalog.voids[iLine].eigenVecs[1][1] = float(line[9])
|
||||
catalog.voids[iLine].eigenVecs[1][2] = float(line[10])
|
||||
|
||||
catalog.voids[iLine].eigenVecs[2][0] = float(line[11])
|
||||
catalog.voids[iLine].eigenVecs[2][1] = float(line[12])
|
||||
catalog.voids[iLine].eigenVecs[2][2] = float(line[13])
|
||||
|
||||
iLine += 1
|
||||
|
||||
if loadParticles:
|
||||
print("Loading all particles...")
|
||||
partData, boxLen, volNorm, isObservationData, ranges, extraData = loadPart(sampleDir)
|
||||
numPartTot = len(partData)
|
||||
catalog.numPartTot = numPartTot
|
||||
catalog.partPos = partData
|
||||
catalog.part = []
|
||||
for i in range(len(partData)):
|
||||
catalog.part.append(Bunch(x = partData[i][0],
|
||||
y = partData[i][1],
|
||||
z = partData[i][2],
|
||||
volume = 0,
|
||||
ra = extraData[i][0],
|
||||
dec = extraData[i][1],
|
||||
redshift = extraData[i][2],
|
||||
uniqueID = extraData[i][3]))
|
||||
|
||||
|
||||
print("Loading volumes...")
|
||||
volFile = sampleDir+"/vol_"+sample.fullName+".dat"
|
||||
with open(volFile, mode="rb") as File:
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
vols = np.fromfile(File, dtype=np.float32,count=numPartTot)
|
||||
for ivol in range(len(vols)):
|
||||
catalog.part[ivol].volume = vols[ivol] / volNorm
|
||||
|
||||
print("Loading zone-void membership info...")
|
||||
zoneFile = sampleDir+"/voidZone_"+sample.fullName+".dat"
|
||||
catalog.void2Zones = []
|
||||
with open(zoneFile, mode="rb") as File:
|
||||
numZonesTot = np.fromfile(File, dtype=np.int32,count=1)[0]
|
||||
catalog.numZonesTot = numZonesTot
|
||||
for iZ in range(numZonesTot):
|
||||
numZones = np.fromfile(File, dtype=np.int32,count=1)[0]
|
||||
catalog.void2Zones.append(Bunch(numZones = numZones,
|
||||
zoneIDs = []))
|
||||
|
||||
for p in range(numZones):
|
||||
zoneID = np.fromfile(File, dtype=np.int32,count=1)[0]
|
||||
catalog.void2Zones[iZ].zoneIDs.append(zoneID)
|
||||
|
||||
print("Loading particle-zone membership info...")
|
||||
zonePartFile = sampleDir+"/voidPart_"+sample.fullName+".dat"
|
||||
catalog.zones2Parts = []
|
||||
with open(zonePartFile) as File:
|
||||
chk = np.fromfile(File, dtype=np.int32,count=1)
|
||||
numZonesTot = np.fromfile(File, dtype=np.int32,count=1)[0]
|
||||
for iZ in range(numZonesTot):
|
||||
numPart = np.fromfile(File, dtype=np.int32,count=1)[0]
|
||||
catalog.zones2Parts.append(Bunch(numPart = numPart,
|
||||
partIDs = []))
|
||||
|
||||
for p in range(numPart):
|
||||
partID = np.fromfile(File, dtype=np.int32,count=1)[0]
|
||||
catalog.zones2Parts[iZ].partIDs.append(partID)
|
||||
|
||||
return catalog
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def getArray(objectList, attr):
|
||||
|
||||
if hasattr(objectList[0], attr):
|
||||
ndim = np.shape( np.atleast_1d( getattr(objectList[0], attr) ) )[0]
|
||||
attrArr = np.zeros(( len(objectList), ndim ))
|
||||
|
||||
for idim in range(ndim):
|
||||
attrArr[:,idim] = np.fromiter((np.atleast_1d(getattr(v, attr))[idim] \
|
||||
for v in objectList), float )
|
||||
|
||||
if ndim == 1: attrArr = attrArr[:,0]
|
||||
|
||||
return attrArr
|
||||
else:
|
||||
print(" Attribute", attr, "not found!")
|
||||
return -1
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def getVoidPart(catalog, voidID):
|
||||
|
||||
partOut = []
|
||||
for iZ in range(catalog.void2Zones[voidID].numZones):
|
||||
zoneID = catalog.void2Zones[voidID].zoneIDs[iZ]
|
||||
for p in range(catalog.zones2Parts[zoneID].numPart):
|
||||
partID = catalog.zones2Parts[zoneID].partIDs[p]
|
||||
partOut.append(catalog.part[partID])
|
||||
|
||||
return partOut
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def filterVoidsOnSize(catalog, rMin):
|
||||
catalog.voids = [v for v in catalog.voids if v.radius >= rMin]
|
||||
catalog.numVoids = len(catalog.voids)
|
||||
return catalog
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def filterVoidsOnTreeLevel(catalog, level):
|
||||
catalog.voids = [v for v in catalog.voids if v.treeLevel == level]
|
||||
if level == -1:
|
||||
catalog.voids = [v for v in catalog.voids if v.numChildren == 0]
|
||||
catalog.numVoids = len(catalog.voids)
|
||||
return catalog
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def filterVoidsOnCentralDen(catalog, maxCentralDen):
|
||||
catalog.voids = [v for v in catalog.voids if v.centralDen <= maxCentralDen]
|
||||
catalog.numVoids = len(catalog.voids)
|
||||
return catalog
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def filterVoidsOnCoreDen(catalog, maxCoreDen):
|
||||
catalog.voids = [v for v in catalog.voids if v.coreDens <= maxCoreDen]
|
||||
catalog.numVoids = len(catalog.voids)
|
||||
return catalog
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def filterVoidsOnDenCon(catalog, minDenCon):
|
||||
catalog.voids = [v for v in catalog.voids if v.densCon >= minDenCon]
|
||||
|
||||
return catalog
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def stackVoids(catalog, stackMode = "ball"):
|
||||
|
||||
# builds a stack of voids from the given catalog
|
||||
# catalog: void catalog
|
||||
# stackMode:
|
||||
# "ball": spherical cut
|
||||
# "voronoi": only void member particles
|
||||
#
|
||||
# returns:
|
||||
# stackedPart: array of relative particle positions in the stack
|
||||
|
||||
rMax = 100.
|
||||
periodicLine = getPeriodic(catalog.sampleInfo)
|
||||
|
||||
if stackMode == "ball":
|
||||
partTree = getPartTree(catalog)
|
||||
|
||||
stackedPart = []
|
||||
for void in catalog.voids:
|
||||
center = void.macrocenter
|
||||
|
||||
if stackMode == "ball":
|
||||
localPart = catalog.partPos[ getBall(partTree, center, rMax) ]
|
||||
else:
|
||||
voidPart = getVoidPart(catalog, void.voidID)
|
||||
localPart = np.zeros((len(voidPart),3))
|
||||
localPart[:,0] = getArray(voidPart, 'x')
|
||||
localPart[:,1] = getArray(voidPart, 'y')
|
||||
localPart[:,2] = getArray(voidPart, 'z')
|
||||
|
||||
shiftedPart = shiftPart(localPart, center, periodicLine, catalog.ranges)
|
||||
|
||||
stackedPart.extend(shiftedPart)
|
||||
|
||||
return stackedPart
|
83
python_source/vide/voidUtil/matchUtil.py
Normal file
83
python_source/vide/voidUtil/matchUtil.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env python
|
||||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/voidUtil/matchUtil.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
__all__=['compareCatalogs',]
|
||||
|
||||
from vide.backend import *
|
||||
import imp
|
||||
import pickle
|
||||
import os
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import argparse
|
||||
|
||||
def compareCatalogs(baseCatalogDir, compareCatalogDir,
|
||||
outputDir="./", logDir="./",
|
||||
matchMethod="useID", dataPortion="central",
|
||||
strictMatch=True,
|
||||
overlapFrac=0.25,
|
||||
pathToCTools="../../../c_tools"):
|
||||
|
||||
# reports the overlap between two void catalogs
|
||||
# baseCatalogDir: directory of catalog 1
|
||||
# compareCatagDir: directory of catalog 2
|
||||
# outputDir: directory to place outputs
|
||||
# logDir: directory to place log files
|
||||
# matchMethod: "useID" to use unique IDs, "prox" to use overlap of Voronoi cells
|
||||
# dataPortion: "central" or "all"
|
||||
# strictMatch: if True, only attempt to match to trimmed catalog
|
||||
# overlapFrac: threshold fraction of Voronoi radius to count as matched
|
||||
# pathToCTools: path to location of VIDE c_tools directory
|
||||
|
||||
if not os.access(outputDir, os.F_OK):
|
||||
os.makedirs(outputDir)
|
||||
|
||||
if not os.access(logDir, os.F_OK):
|
||||
os.makedirs(logDir)
|
||||
|
||||
outFileName = outputDir + "/" + "voidOverlap" #+ ".dat"
|
||||
|
||||
with open(baseCatalogDir+"/sample_info.dat", 'rb') as input:
|
||||
baseSample = pickle.load(input)
|
||||
|
||||
with open(compareCatalogDir+"/sample_info.dat", 'rb') as input:
|
||||
sample = pickle.load(input)
|
||||
|
||||
print(" Comparing", baseSample.fullName, "to", sample.fullName, "...", end=' ')
|
||||
sys.stdout.flush()
|
||||
|
||||
sampleName = sample.fullName
|
||||
|
||||
binPath = pathToCTools+"/analysis/voidOverlap"
|
||||
logFile = logDir+"/compare_"+baseSample.fullName+"_"+sampleName+".out"
|
||||
stepOutputFileName = outFileName + "_" + baseSample.fullName + "_" + \
|
||||
sampleName + "_"
|
||||
|
||||
launchVoidOverlap(baseSample, sample, baseCatalogDir,
|
||||
compareCatalogDir, binPath,
|
||||
thisDataPortion=dataPortion, logFile=logFile,
|
||||
continueRun=False,
|
||||
outputFile=stepOutputFileName,
|
||||
matchMethod=matchMethod,
|
||||
overlapFrac=overlapFrac,
|
||||
strictMatch=strictMatch)
|
||||
|
||||
print(" Done!")
|
||||
return
|
394
python_source/vide/voidUtil/periodic_kdtree.py
Normal file
394
python_source/vide/voidUtil/periodic_kdtree.py
Normal file
|
@ -0,0 +1,394 @@
|
|||
# periodic_kdtree.py
|
||||
#
|
||||
# A wrapper around scipy.spatial.kdtree to implement periodic boundary
|
||||
# conditions
|
||||
#
|
||||
# Written by Patrick Varilly, 6 Jul 2012
|
||||
# Released under the scipy license
|
||||
|
||||
import numpy as np
|
||||
from scipy.spatial import KDTree, cKDTree
|
||||
import itertools
|
||||
import heapq
|
||||
|
||||
def _gen_relevant_images(x, bounds, distance_upper_bound):
|
||||
# Map x onto the canonical unit cell, then produce the relevant
|
||||
# mirror images
|
||||
real_x = x - np.where(bounds > 0.0,
|
||||
np.floor(x / bounds) * bounds, 0.0)
|
||||
m = len(x)
|
||||
|
||||
xs_to_try = [real_x]
|
||||
for i in range(m):
|
||||
if bounds[i] > 0.0:
|
||||
disp = np.zeros(m)
|
||||
disp[i] = bounds[i]
|
||||
|
||||
if distance_upper_bound == np.inf:
|
||||
xs_to_try = list(
|
||||
itertools.chain.from_iterable(
|
||||
(_ + disp, _, _ - disp) for _ in xs_to_try))
|
||||
else:
|
||||
extra_xs = []
|
||||
|
||||
# Point near lower boundary, include image on upper side
|
||||
if abs(real_x[i]) < distance_upper_bound:
|
||||
extra_xs.extend(_ + disp for _ in xs_to_try)
|
||||
|
||||
# Point near upper boundary, include image on lower side
|
||||
if abs(bounds[i] - real_x[i]) < distance_upper_bound:
|
||||
extra_xs.extend(_ - disp for _ in xs_to_try)
|
||||
|
||||
xs_to_try.extend(extra_xs)
|
||||
|
||||
return xs_to_try
|
||||
|
||||
|
||||
class PeriodicKDTree(KDTree):
|
||||
"""
|
||||
kd-tree for quick nearest-neighbor lookup with periodic boundaries
|
||||
|
||||
See scipy.spatial.kdtree for details on kd-trees.
|
||||
|
||||
Searches with periodic boundaries are implemented by mapping all
|
||||
initial data points to one canonical periodic image, building an
|
||||
ordinary kd-tree with these points, then querying this kd-tree multiple
|
||||
times, if necessary, with all the relevant periodic images of the
|
||||
query point.
|
||||
|
||||
Note that to ensure that no two distinct images of the same point
|
||||
appear in the results, it is essential to restrict the maximum
|
||||
distance between a query point and a data point to half the smallest
|
||||
box dimension.
|
||||
"""
|
||||
|
||||
def __init__(self, bounds, data, leafsize=10):
|
||||
"""Construct a kd-tree.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bounds : array_like, shape (k,)
|
||||
Size of the periodic box along each spatial dimension. A
|
||||
negative or zero size for dimension k means that space is not
|
||||
periodic along k.
|
||||
data : array_like, shape (n,k)
|
||||
The data points to be indexed. This array is not copied, and
|
||||
so modifying this data will result in bogus results.
|
||||
leafsize : positive int
|
||||
The number of points at which the algorithm switches over to
|
||||
brute-force.
|
||||
"""
|
||||
|
||||
# Map all points to canonical periodic image
|
||||
self.bounds = np.array(bounds)
|
||||
self.real_data = np.asarray(data)
|
||||
wrapped_data = (
|
||||
self.real_data - np.where(bounds > 0.0,
|
||||
(np.floor(self.real_data / bounds) * bounds), 0.0))
|
||||
|
||||
# Calculate maximum distance_upper_bound
|
||||
self.max_distance_upper_bound = np.min(
|
||||
np.where(self.bounds > 0, 0.5 * self.bounds, np.inf))
|
||||
|
||||
# Set up underlying kd-tree
|
||||
super(PeriodicKDTree, self).__init__(wrapped_data, leafsize)
|
||||
|
||||
# The following name is a kludge to override KDTree's private method
|
||||
def _KDTree__query(self, x, k=1, eps=0, p=2, distance_upper_bound=np.inf):
|
||||
# This is the internal query method, which guarantees that x
|
||||
# is a single point, not an array of points
|
||||
#
|
||||
# A slight complication: k could be "None", which means "return
|
||||
# all neighbors within the given distance_upper_bound".
|
||||
|
||||
# Cap distance_upper_bound
|
||||
distance_upper_bound = min([distance_upper_bound,
|
||||
self.max_distance_upper_bound])
|
||||
|
||||
# Run queries over all relevant images of x
|
||||
hits_list = []
|
||||
for real_x in _gen_relevant_images(x, self.bounds, distance_upper_bound):
|
||||
hits_list.append(
|
||||
super(PeriodicKDTree, self)._KDTree__query(
|
||||
real_x, k, eps, p, distance_upper_bound))
|
||||
|
||||
# Now merge results
|
||||
if k is None:
|
||||
return list(heapq.merge(*hits_list))
|
||||
elif k > 1:
|
||||
return heapq.nsmallest(k, itertools.chain(*hits_list))
|
||||
elif k == 1:
|
||||
return [min(itertools.chain(*hits_list))]
|
||||
else:
|
||||
raise ValueError("Invalid k in periodic_kdtree._KDTree__query")
|
||||
|
||||
# The following name is a kludge to override KDTree's private method
|
||||
def _KDTree__query_ball_point(self, x, r, p=2., eps=0):
|
||||
# This is the internal query method, which guarantees that x
|
||||
# is a single point, not an array of points
|
||||
|
||||
# Cap r
|
||||
r = min(r, self.max_distance_upper_bound)
|
||||
|
||||
# Run queries over all relevant images of x
|
||||
results = []
|
||||
for real_x in _gen_relevant_images(x, self.bounds, r):
|
||||
results.extend(
|
||||
super(PeriodicKDTree, self)._KDTree__query_ball_point(
|
||||
real_x, r, p, eps))
|
||||
return results
|
||||
|
||||
def query_ball_tree(self, other, r, p=2., eps=0):
|
||||
raise NotImplementedError()
|
||||
|
||||
def query_pairs(self, r, p=2., eps=0):
|
||||
raise NotImplementedError()
|
||||
|
||||
def count_neighbors(self, other, r, p=2.):
|
||||
raise NotImplementedError()
|
||||
|
||||
def sparse_distance_matrix(self, other, max_distance, p=2.):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class PeriodicCKDTree(cKDTree):
|
||||
"""
|
||||
Cython kd-tree for quick nearest-neighbor lookup with periodic boundaries
|
||||
|
||||
See scipy.spatial.ckdtree for details on kd-trees.
|
||||
|
||||
Searches with periodic boundaries are implemented by mapping all
|
||||
initial data points to one canonical periodic image, building an
|
||||
ordinary kd-tree with these points, then querying this kd-tree multiple
|
||||
times, if necessary, with all the relevant periodic images of the
|
||||
query point.
|
||||
|
||||
Note that to ensure that no two distinct images of the same point
|
||||
appear in the results, it is essential to restrict the maximum
|
||||
distance between a query point and a data point to half the smallest
|
||||
box dimension.
|
||||
"""
|
||||
|
||||
def __init__(self, bounds, data, leafsize=10):
|
||||
"""Construct a kd-tree.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bounds : array_like, shape (k,)
|
||||
Size of the periodic box along each spatial dimension. A
|
||||
negative or zero size for dimension k means that space is not
|
||||
periodic along k.
|
||||
data : array-like, shape (n,m)
|
||||
The n data points of dimension mto be indexed. This array is
|
||||
not copied unless this is necessary to produce a contiguous
|
||||
array of doubles, and so modifying this data will result in
|
||||
bogus results.
|
||||
leafsize : positive integer
|
||||
The number of points at which the algorithm switches over to
|
||||
brute-force.
|
||||
"""
|
||||
|
||||
# Map all points to canonical periodic image
|
||||
self.bounds = np.array(bounds)
|
||||
self.real_data = np.asarray(data)
|
||||
wrapped_data = (
|
||||
self.real_data - np.where(bounds > 0.0,
|
||||
(np.floor(self.real_data / bounds) * bounds), 0.0))
|
||||
|
||||
# Calculate maximum distance_upper_bound
|
||||
self.max_distance_upper_bound = np.min(
|
||||
np.where(self.bounds > 0, 0.5 * self.bounds, np.inf))
|
||||
|
||||
# Set up underlying kd-tree
|
||||
super(PeriodicCKDTree, self).__init__(wrapped_data, leafsize)
|
||||
|
||||
# Ideally, KDTree and cKDTree would expose identical query and __query
|
||||
# interfaces. But they don't, and cKDTree.__query is also inaccessible
|
||||
# from Python. We do our best here to cope.
|
||||
def __query(self, x, k=1, eps=0, p=2, distance_upper_bound=np.inf):
|
||||
# This is the internal query method, which guarantees that x
|
||||
# is a single point, not an array of points
|
||||
#
|
||||
# A slight complication: k could be "None", which means "return
|
||||
# all neighbors within the given distance_upper_bound".
|
||||
|
||||
# Cap distance_upper_bound
|
||||
distance_upper_bound = np.min([distance_upper_bound,
|
||||
self.max_distance_upper_bound])
|
||||
|
||||
# Run queries over all relevant images of x
|
||||
hits_list = []
|
||||
for real_x in _gen_relevant_images(x, self.bounds, distance_upper_bound):
|
||||
d, i = super(PeriodicCKDTree, self).query(
|
||||
real_x, k, eps, p, distance_upper_bound)
|
||||
if k > 1:
|
||||
hits_list.append(list(zip(d, i)))
|
||||
else:
|
||||
hits_list.append([(d, i)])
|
||||
|
||||
# Now merge results
|
||||
if k > 1:
|
||||
return heapq.nsmallest(k, itertools.chain(*hits_list))
|
||||
elif k == 1:
|
||||
return [min(itertools.chain(*hits_list))]
|
||||
else:
|
||||
raise ValueError("Invalid k in periodic_kdtree._KDTree__query")
|
||||
|
||||
def query(self, x, k=1, eps=0, p=2, distance_upper_bound=np.inf):
|
||||
"""
|
||||
Query the kd-tree for nearest neighbors
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like, last dimension self.m
|
||||
An array of points to query.
|
||||
k : integer
|
||||
The number of nearest neighbors to return.
|
||||
eps : non-negative float
|
||||
Return approximate nearest neighbors; the kth returned value
|
||||
is guaranteed to be no further than (1+eps) times the
|
||||
distance to the real k-th nearest neighbor.
|
||||
p : float, 1<=p<=infinity
|
||||
Which Minkowski p-norm to use.
|
||||
1 is the sum-of-absolute-values "Manhattan" distance
|
||||
2 is the usual Euclidean distance
|
||||
infinity is the maximum-coordinate-difference distance
|
||||
distance_upper_bound : nonnegative float
|
||||
Return only neighbors within this distance. This is used to prune
|
||||
tree searches, so if you are doing a series of nearest-neighbor
|
||||
queries, it may help to supply the distance to the nearest neighbor
|
||||
of the most recent point.
|
||||
|
||||
Returns
|
||||
-------
|
||||
d : array of floats
|
||||
The distances to the nearest neighbors.
|
||||
If x has shape tuple+(self.m,), then d has shape tuple+(k,).
|
||||
Missing neighbors are indicated with infinite distances.
|
||||
i : ndarray of ints
|
||||
The locations of the neighbors in self.data.
|
||||
If `x` has shape tuple+(self.m,), then `i` has shape tuple+(k,).
|
||||
Missing neighbors are indicated with self.n.
|
||||
|
||||
"""
|
||||
x = np.asarray(x)
|
||||
if np.shape(x)[-1] != self.m:
|
||||
raise ValueError("x must consist of vectors of length %d but has shape %s" % (self.m, np.shape(x)))
|
||||
if p<1:
|
||||
raise ValueError("Only p-norms with 1<=p<=infinity permitted")
|
||||
retshape = np.shape(x)[:-1]
|
||||
if retshape!=():
|
||||
if k>1:
|
||||
dd = np.empty(retshape+(k,),dtype=np.float)
|
||||
dd.fill(np.inf)
|
||||
ii = np.empty(retshape+(k,),dtype=np.int)
|
||||
ii.fill(self.n)
|
||||
elif k==1:
|
||||
dd = np.empty(retshape,dtype=np.float)
|
||||
dd.fill(np.inf)
|
||||
ii = np.empty(retshape,dtype=np.int)
|
||||
ii.fill(self.n)
|
||||
else:
|
||||
raise ValueError("Requested %s nearest neighbors; acceptable numbers are integers greater than or equal to one, or None")
|
||||
for c in np.ndindex(retshape):
|
||||
hits = self.__query(x[c], k=k, eps=eps, p=p, distance_upper_bound=distance_upper_bound)
|
||||
if k>1:
|
||||
for j in range(len(hits)):
|
||||
dd[c+(j,)], ii[c+(j,)] = hits[j]
|
||||
elif k==1:
|
||||
if len(hits)>0:
|
||||
dd[c], ii[c] = hits[0]
|
||||
else:
|
||||
dd[c] = np.inf
|
||||
ii[c] = self.n
|
||||
return dd, ii
|
||||
else:
|
||||
hits = self.__query(x, k=k, eps=eps, p=p, distance_upper_bound=distance_upper_bound)
|
||||
if k==1:
|
||||
if len(hits)>0:
|
||||
return hits[0]
|
||||
else:
|
||||
return np.inf, self.n
|
||||
elif k>1:
|
||||
dd = np.empty(k,dtype=np.float)
|
||||
dd.fill(np.inf)
|
||||
ii = np.empty(k,dtype=np.int)
|
||||
ii.fill(self.n)
|
||||
for j in range(len(hits)):
|
||||
dd[j], ii[j] = hits[j]
|
||||
return dd, ii
|
||||
else:
|
||||
raise ValueError("Requested %s nearest neighbors; acceptable numbers are integers greater than or equal to one, or None")
|
||||
|
||||
# Ideally, KDTree and cKDTree would expose identical __query_ball_point
|
||||
# interfaces. But they don't, and cKDTree.__query_ball_point is also
|
||||
# inaccessible from Python. We do our best here to cope.
|
||||
def __query_ball_point(self, x, r, p=2., eps=0):
|
||||
# This is the internal query method, which guarantees that x
|
||||
# is a single point, not an array of points
|
||||
|
||||
# Cap r
|
||||
r = min(r, self.max_distance_upper_bound)
|
||||
|
||||
# Run queries over all relevant images of x
|
||||
results = []
|
||||
for real_x in _gen_relevant_images(x, self.bounds, r):
|
||||
results.extend(super(PeriodicCKDTree, self).query_ball_point(
|
||||
real_x, r, p, eps))
|
||||
return results
|
||||
|
||||
def query_ball_point(self, x, r, p=2., eps=0):
|
||||
"""
|
||||
Find all points within distance r of point(s) x.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : array_like, shape tuple + (self.m,)
|
||||
The point or points to search for neighbors of.
|
||||
r : positive float
|
||||
The radius of points to return.
|
||||
p : float, optional
|
||||
Which Minkowski p-norm to use. Should be in the range [1, inf].
|
||||
eps : nonnegative float, optional
|
||||
Approximate search. Branches of the tree are not explored if their
|
||||
nearest points are further than ``r / (1 + eps)``, and branches are
|
||||
added in bulk if their furthest points are nearer than
|
||||
``r * (1 + eps)``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
results : list or array of lists
|
||||
If `x` is a single point, returns a list of the indices of the
|
||||
neighbors of `x`. If `x` is an array of points, returns an object
|
||||
array of shape tuple containing lists of neighbors.
|
||||
|
||||
Notes
|
||||
-----
|
||||
If you have many points whose neighbors you want to find, you may
|
||||
save substantial amounts of time by putting them in a
|
||||
PeriodicCKDTree and using query_ball_tree.
|
||||
"""
|
||||
x = np.asarray(x).astype(np.float)
|
||||
if x.shape[-1] != self.m:
|
||||
raise ValueError("Searching for a %d-dimensional point in a " \
|
||||
"%d-dimensional KDTree" % (x.shape[-1], self.m))
|
||||
if len(x.shape) == 1:
|
||||
return self.__query_ball_point(x, r, p, eps)
|
||||
else:
|
||||
retshape = x.shape[:-1]
|
||||
result = np.empty(retshape, dtype=np.object)
|
||||
for c in np.ndindex(retshape):
|
||||
result[c] = self.__query_ball_point(x[c], r, p, eps)
|
||||
return result
|
||||
|
||||
def query_ball_tree(self, other, r, p=2., eps=0):
|
||||
raise NotImplementedError()
|
||||
|
||||
def query_pairs(self, r, p=2., eps=0):
|
||||
raise NotImplementedError()
|
||||
|
||||
def count_neighbors(self, other, r, p=2.):
|
||||
raise NotImplementedError()
|
||||
|
||||
def sparse_distance_matrix(self, other, max_distance, p=2.):
|
||||
raise NotImplementedError()
|
33
python_source/vide/voidUtil/plotDefs.py
Normal file
33
python_source/vide/voidUtil/plotDefs.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/voidUtil/plotDefs.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
LIGHT_SPEED = 299792.458
|
||||
|
||||
colorList = ['r', 'b', 'g', 'y', 'c', 'm',
|
||||
'darkred', 'grey',
|
||||
'orange', 'darkblue',
|
||||
'indigo', 'lightseagreen', 'maroon', 'olive',
|
||||
'royalblue', 'palevioletred', 'seagreen', 'tomato',
|
||||
'aquamarine', 'darkslateblue',
|
||||
'khaki', 'lawngreen', 'mediumorchid',
|
||||
'orangered', 'thistle'
|
||||
'yellowgreen']
|
||||
|
||||
linewidth = 4
|
||||
fontsize = 12
|
298
python_source/vide/voidUtil/plotUtil.py
Normal file
298
python_source/vide/voidUtil/plotUtil.py
Normal file
|
@ -0,0 +1,298 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/voidUtil/plotUtil.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
__all__=['plotNumberFunction','plotEllipDist','plotVoidCells']
|
||||
|
||||
from vide.backend.classes import *
|
||||
from .plotDefs import *
|
||||
import numpy as np
|
||||
import os
|
||||
import pylab as plt
|
||||
import vide.backend.cosmologyTools as vp
|
||||
from vide.voidUtil import getArray, shiftPart, getVoidPart
|
||||
|
||||
def fill_between(x, y1, y2=0, ax=None, **kwargs):
|
||||
"""Plot filled region between `y1` and `y2`.
|
||||
|
||||
This function works exactly the same as matplotlib's fill_between, except
|
||||
that it also plots a proxy artist (specifically, a rectangle of 0 size)
|
||||
so that it can be added it appears on a legend.
|
||||
"""
|
||||
ax = ax if ax is not None else plt.gca()
|
||||
ax.fill_between(x, y1, y2, interpolate=True, **kwargs)
|
||||
p = plt.Rectangle((0, 0), 0, 0, **kwargs)
|
||||
ax.add_patch(p)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def plotNumberFunction(catalogList,
|
||||
figDir="./",
|
||||
plotName="numberfunc",
|
||||
cumulative=True,
|
||||
binWidth=1):
|
||||
|
||||
# plots a cumulative number function
|
||||
# catalogList: list of void catalogs to plot
|
||||
# figDir: output directory for figures
|
||||
# plotName: name to prefix to all outputs
|
||||
# cumulative: if True, plots cumulative number function
|
||||
# binWidth: width of histogram bins in Mpc/h
|
||||
# returns:
|
||||
# ellipDistList: array of len(catalogList),
|
||||
# each element has array of size bins, number, +/- 1 sigma
|
||||
|
||||
print("Plotting number function")
|
||||
|
||||
catalogList = np.atleast_1d(catalogList)
|
||||
|
||||
plt.clf()
|
||||
plt.xlabel("$R_{eff}$ [$h^{-1}Mpc$]", fontsize=14)
|
||||
|
||||
if cumulative:
|
||||
plt.ylabel(r"log ($n$ (> R) [$h^3$ Gpc$^{-3}$])", fontsize=14)
|
||||
else:
|
||||
plt.ylabel(r"log ($dn/dR$ [$h^3$ Gpc$^{-3}$])", fontsize=14)
|
||||
|
||||
ellipDistList = []
|
||||
|
||||
for (iSample,catalog) in enumerate(catalogList):
|
||||
sample = catalog.sampleInfo
|
||||
data = getArray(catalog.voids, 'radius')
|
||||
|
||||
if sample.dataType == "observation":
|
||||
maskFile = sample.maskFile
|
||||
|
||||
boxVol = vp.getSurveyProps(maskFile,
|
||||
sample.zBoundary[0], sample.zBoundary[1],
|
||||
sample.zRange[0], sample.zRange[1], "all",
|
||||
selectionFuncFile=sample.selFunFile)[0]
|
||||
else:
|
||||
boxVol = sample.boxLen*sample.boxLen*(sample.zBoundaryMpc[1] -
|
||||
sample.zBoundaryMpc[0])
|
||||
|
||||
boxVol *= 1.e-9 # Mpc->Gpc
|
||||
|
||||
bins = 100./binWidth
|
||||
hist, binEdges = np.histogram(data, bins=bins, range=(0., 100.))
|
||||
binCenters = 0.5*(binEdges[1:] + binEdges[:-1])
|
||||
|
||||
if cumulative:
|
||||
foundStart = False
|
||||
for iBin in range(len(hist)):
|
||||
if not foundStart and hist[iBin] == 0:
|
||||
continue
|
||||
foundStart = True
|
||||
hist[iBin] = np.sum(hist[iBin:])
|
||||
|
||||
nvoids = len(data)
|
||||
var = hist * (1. - hist/nvoids)
|
||||
sig = np.sqrt(var)
|
||||
|
||||
lowerbound = hist - sig
|
||||
upperbound = hist + sig
|
||||
|
||||
mean = np.log10(hist/boxVol)
|
||||
lowerbound = np.log10(lowerbound/boxVol)
|
||||
upperbound = np.log10(upperbound/boxVol)
|
||||
|
||||
lineColor = colorList[iSample]
|
||||
lineTitle = sample.fullName
|
||||
|
||||
trim = (lowerbound > .01)
|
||||
mean = mean[trim]
|
||||
binCentersToUse = binCenters[trim]
|
||||
lower = lowerbound[trim]
|
||||
upper = upperbound[trim]
|
||||
|
||||
alpha = 0.55
|
||||
fill_between(binCentersToUse, lower, upper,
|
||||
label=lineTitle, color=lineColor,
|
||||
alpha=alpha,
|
||||
)
|
||||
|
||||
lineStyle = '-'
|
||||
plt.plot(binCentersToUse, mean, lineStyle,
|
||||
color=lineColor,
|
||||
linewidth=3)
|
||||
|
||||
ellipDistList.append((binCentersToUse, mean, lower, upper))
|
||||
|
||||
plt.legend(loc = "upper right", fancybox=True, prop={'size':14})
|
||||
|
||||
plt.savefig(figDir+"/fig_"+plotName+".pdf", bbox_inches="tight")
|
||||
plt.savefig(figDir+"/fig_"+plotName+".eps", bbox_inches="tight")
|
||||
plt.savefig(figDir+"/fig_"+plotName+".png", bbox_inches="tight")
|
||||
|
||||
return ellipDistList
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def plotEllipDist(catalogList,
|
||||
figDir="./",
|
||||
plotName="ellipdist"):
|
||||
|
||||
# plots ellipticity distributions
|
||||
# catalogList: list of void catalogs to plot
|
||||
# figDir: output directory for figures
|
||||
# plotName: name to prefix to all outputs
|
||||
# returns:
|
||||
# ellipDistList: array of len(catalogList),
|
||||
# each element has array of ellipticity distributions
|
||||
|
||||
print("Plotting ellipticity distributions")
|
||||
|
||||
plt.clf()
|
||||
plt.xlabel(r"Ellipticity $\epsilon$", fontsize=14)
|
||||
plt.ylabel(r"P($\epsilon$)", fontsize=14)
|
||||
|
||||
ellipDistList = []
|
||||
|
||||
catalogList = np.atleast_1d(catalogList)
|
||||
|
||||
for (iSample,catalog) in enumerate(catalogList):
|
||||
sample = catalog.sampleInfo
|
||||
data = getArray(catalog.voids, 'ellipticity')
|
||||
|
||||
dataWeights = np.ones_like(data)/len(data)
|
||||
dataHist, dataBins = np.histogram(data, bins=10, weights=dataWeights,
|
||||
range=(0.0,0.35))
|
||||
binCenters = 0.5*(dataBins[1:] + dataBins[:-1])
|
||||
|
||||
plt.plot(binCenters, dataHist, label=sample.fullName,
|
||||
color=colorList[iSample])
|
||||
|
||||
ellipDistList.append((dataBins, dataHist,))
|
||||
|
||||
plt.legend(loc = "upper right", fancybox=True, prop={'size':14})
|
||||
|
||||
plt.savefig(figDir+"/fig_"+plotName+".pdf", bbox_inches="tight")
|
||||
plt.savefig(figDir+"/fig_"+plotName+".eps", bbox_inches="tight")
|
||||
plt.savefig(figDir+"/fig_"+plotName+".png", bbox_inches="tight")
|
||||
|
||||
return
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def plotVoidCells(catalog,
|
||||
voidID,
|
||||
figDir="./",
|
||||
plotName="cells",
|
||||
plotDensity=True,
|
||||
sliceWidth=250):
|
||||
|
||||
# plots the particles belonging to a void
|
||||
# catalog: void catalog
|
||||
# voidID: ID of void to plot
|
||||
# figDir: output directory for figures
|
||||
# plotName: name to prefix to all outputs
|
||||
# sliceWidth: width of slice in Mpc/h
|
||||
|
||||
sample = catalog.sampleInfo
|
||||
periodicLine = getPeriodic(sample)
|
||||
|
||||
plt.clf()
|
||||
|
||||
iVoid = -1
|
||||
for i in range(len(catalog.voids)):
|
||||
if catalog.voids[i].voidID == voidID:
|
||||
iVoid = i
|
||||
break
|
||||
|
||||
if iVoid == -1:
|
||||
print("Void ID %d not found!" % voidID)
|
||||
return
|
||||
|
||||
sliceCenter = catalog.voids[iVoid].macrocenter
|
||||
|
||||
xwidth = sliceWidth
|
||||
ywidth = sliceWidth
|
||||
zwidth = max(sliceWidth/4., 50)
|
||||
|
||||
xmin = -xwidth/2.
|
||||
xmax = xwidth/2.
|
||||
ymin = -ywidth/2.
|
||||
ymax = ywidth/2.
|
||||
zmin = -zwidth/2.
|
||||
zmax = zwidth/2.
|
||||
|
||||
#Slice Particles
|
||||
if plotDensity:
|
||||
part = catalog.partPos
|
||||
part = shiftPart(part, sliceCenter, periodicLine, catalog.ranges)
|
||||
|
||||
filter = (part[:,0] > xmin) & (part[:,0] < xmax) & \
|
||||
(part[:,1] > ymin) & (part[:,1] < ymax) & \
|
||||
(part[:,2] > zmin) & (part[:,2] < zmax)
|
||||
part = part[filter]
|
||||
|
||||
extent = [xmin, xmax, ymin, ymax]
|
||||
hist, xedges, yedges = np.histogram2d(part[:,0], part[:,1], normed=False,
|
||||
bins=64)
|
||||
|
||||
hist = np.log10(hist+1)
|
||||
plt.imshow(hist,
|
||||
aspect='equal',
|
||||
extent=extent,
|
||||
interpolation='gaussian',
|
||||
cmap='YlGnBu_r')
|
||||
|
||||
|
||||
# overlay voids as circles
|
||||
fig = plt.gcf()
|
||||
|
||||
voidPart = getVoidPart(catalog, voidID)
|
||||
|
||||
newpart = np.zeros((len(voidPart),3))
|
||||
volume=np.zeros(len(voidPart))
|
||||
radius=np.zeros(len(voidPart))
|
||||
|
||||
newpart[:,0] = getArray(voidPart, 'x')
|
||||
newpart[:,1] = getArray(voidPart, 'y')
|
||||
newpart[:,2] = getArray(voidPart, 'z')
|
||||
|
||||
volume = getArray(voidPart, 'volume')
|
||||
radius = (3.*volume/(4.*np.pi))**(1./3.)
|
||||
|
||||
shiftedPartVoid =shiftPart(newpart,sliceCenter, periodicLine, catalog.ranges)
|
||||
|
||||
#Limiting plotted cells to cells into the slice
|
||||
#Possibility to only plot bigger cells (through cellsradiuslim)
|
||||
cellsMinlimz = zmin
|
||||
cellsMaxlimz = zmax
|
||||
cellsradiuslim = 0.0
|
||||
|
||||
for p in range(len(volume)):
|
||||
if (shiftedPartVoid[p,2]>(cellsMinlimz) and \
|
||||
shiftedPartVoid[p,2]<(cellsMaxlimz) and \
|
||||
radius[p]>cellsradiuslim):
|
||||
color = 'blue'
|
||||
circle = plt.Circle((shiftedPartVoid[p,0], \
|
||||
shiftedPartVoid[p,1]), \
|
||||
radius[p],
|
||||
alpha =.2, fc=color,edgecolor=None,linewidth=1)
|
||||
fig.gca().add_artist(circle)
|
||||
|
||||
title="cells"+str(voidID)
|
||||
plt.title(title, fontsize=20)
|
||||
plotName="cells"+str(voidID)
|
||||
|
||||
plt.savefig(figDir+"/fig_"+plotName+".pdf", bbox_inches="tight")
|
||||
plt.savefig(figDir+"/fig_"+plotName+".eps", bbox_inches="tight")
|
||||
plt.savefig(figDir+"/fig_"+plotName+".png", bbox_inches="tight")
|
||||
|
||||
return
|
213
python_source/vide/voidUtil/profileUtil.py
Normal file
213
python_source/vide/voidUtil/profileUtil.py
Normal file
|
@ -0,0 +1,213 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/voidUtil/profileUtil.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
__all__=['buildProfile','fitHSWProfile','getHSWProfile',]
|
||||
|
||||
from vide.backend.classes import *
|
||||
from vide.voidUtil import *
|
||||
from .plotDefs import *
|
||||
import numpy as np
|
||||
import os
|
||||
import vide.apTools as vp
|
||||
from scipy.optimize import curve_fit
|
||||
from scipy.interpolate import interp1d
|
||||
|
||||
def HSWProfile(r, rs, dc):
|
||||
alpha = -2.0*rs + 4.0
|
||||
if rs < 0.91:
|
||||
beta = 17.5*rs - 6.5
|
||||
else:
|
||||
beta = -9.8*rs + 18.4
|
||||
return dc * (1 - (r/rs)**alpha) / (1+ (r)**beta) + 1
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def buildProfile(catalog, rMin, rMax, nBins=10):
|
||||
|
||||
# builds a stacked radial density profile from the given catalog
|
||||
# catalog: void catalog
|
||||
# rMin: minimum void radius, in Mpc/h
|
||||
# rMax: maximum void radius, in Mpc/h
|
||||
# nBins: number of bins in profile (detaulf 10)
|
||||
#
|
||||
# returns:
|
||||
# binCenters: array of radii in binned profile
|
||||
# stackedProfile: the stacked density profile
|
||||
# sigmas: 1-sigma uncertainty in each bin
|
||||
|
||||
rMaxProfile = rMin*3 + 2
|
||||
periodicLine = getPeriodic(catalog.sampleInfo)
|
||||
|
||||
print(" Building particle tree...")
|
||||
partTree = getPartTree(catalog)
|
||||
|
||||
print(" Selecting voids to stack...")
|
||||
voidsToStack = [v for v in catalog.voids if (v.radius > rMin and v.radius < rMax)]
|
||||
|
||||
if len(voidsToStack) == 0:
|
||||
print(" No voids to stack!")
|
||||
return -1, -1, -1
|
||||
|
||||
print(" Stacking voids...")
|
||||
allProfiles = []
|
||||
for void in voidsToStack:
|
||||
center = void.macrocenter
|
||||
|
||||
localPart = catalog.partPos[ getBall(partTree, center, rMaxProfile) ]
|
||||
shiftedPart = shiftPart(localPart, center, periodicLine, catalog.ranges)
|
||||
|
||||
dist = np.sqrt(np.sum(shiftedPart[:,:]**2, axis=1))
|
||||
thisProfile, radii = np.histogram(dist, bins=nBins, range=(0,rMaxProfile))
|
||||
deltaV = 4*np.pi/3*(radii[1:]**3-radii[0:(radii.size-1)]**3)
|
||||
thisProfile = np.float32(thisProfile)
|
||||
thisProfile /= deltaV
|
||||
thisProfile /= catalog.volNorm
|
||||
allProfiles.append(thisProfile)
|
||||
binCenters = 0.5*(radii[1:] + radii[:-1])
|
||||
|
||||
nVoids = len(voidsToStack)
|
||||
stackedProfile = np.mean(allProfiles, axis=0)
|
||||
sigmas = np.std(allProfiles, axis=0) / np.sqrt(nVoids)
|
||||
|
||||
return binCenters, stackedProfile, sigmas
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def fitHSWProfile(radii, densities, sigmas, rV):
|
||||
|
||||
# fits the given density profile to the HSW function
|
||||
# radii: array of radii
|
||||
# densities: array of densities in units of mean density
|
||||
# sigmas: array of uncertainties
|
||||
# rV: mean effective void radius
|
||||
#
|
||||
# returns:
|
||||
# popt: best-fit values of rs and dc
|
||||
# pcov: covariance matrix
|
||||
# rVals: array of radii for best-fit curve
|
||||
# hswProfile: array of densities for best-fit curve in units of mean density
|
||||
|
||||
popt, pcov = curve_fit(HSWProfile, radii/rV, densities,
|
||||
sigma=sigmas,
|
||||
maxfev=10000, xtol=5.e-3,
|
||||
p0=[1.0,-1.0])
|
||||
|
||||
# return best-fits
|
||||
rVals = np.linspace(0.0, radii[-1], 100) / rV
|
||||
return popt, pcov, rVals*rV, HSWProfile(rVals,popt[0],popt[1])
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
def getHSWProfile(density, radius):
|
||||
|
||||
# returns the HSW profile for the given sample density and void size
|
||||
# will interpolate/extrapole the radius
|
||||
|
||||
# density: choice of sample (see arXiv:1309.5087):
|
||||
# maxDM: DM at 1 particles per cubic Mpc/h
|
||||
# fullDM: DM at 0.01 particles per cubic Mpc/h
|
||||
# denseDM: DM at 4.e-3 particles per cubic Mpc/h
|
||||
# sparseDM: DM at 3.e-4 particles per cubic Mpc/h
|
||||
#
|
||||
# denseHalos: halos at 4.e-3 particles per cubic Mpc/h
|
||||
# sparseHalos: halos at 3.e-4 particles per cubic Mpc/h
|
||||
#
|
||||
# denseGal: galaxies at 4.e-3 particles per cubic Mpc/h
|
||||
# sparseGal: galaxies at 3.e-4 particles per cubic Mpc/h
|
||||
#
|
||||
# radius: void size in Mpc/h
|
||||
|
||||
# returns:
|
||||
# (rs, dc): best-fit values
|
||||
# binCenters: array of radii in binned profile
|
||||
# stackedProfile: the density profile
|
||||
|
||||
samples = [
|
||||
{'name': 'maxDM',
|
||||
'rv': [8.74041095, 11.65557095, 15.54746657, 20.94913774, 28.41063131, 38.61523696, 51.85944898, 69.42297033],
|
||||
'rs': [0.74958738, 0.79650829, 0.86245251, 0.93960051, 1.01595177, 1.13159483, 1.31457096, 1.65611709],
|
||||
'dc': [-0.95353184, -0.94861939, -0.91888455, -0.84480086, -0.73431544, -0.62614422, -0.54908132, -0.4912146],
|
||||
},
|
||||
{'name': 'fullDM',
|
||||
'rv': [10, 15, 20, 25, 30, 35],
|
||||
'rs': [ 0.76986779, 0.80980775, 0.86590177, 0.93732629, 1.02643542,
|
||||
1.12875503],
|
||||
'dc': [-0.81021 , -0.78115474, -0.78326026, -0.78670109, -0.76626508,
|
||||
-0.72531084],
|
||||
},
|
||||
{'name': 'denseDM',
|
||||
'rv': [10, 15, 20, 25, 30, 35, 40],
|
||||
'rs': [0.7477462 , 0.79932797, 0.84369297, 0.90309363, 0.92990401,
|
||||
1.06970842, 1.16393474],
|
||||
'dc': [-0.78333107, -0.75780925, -0.71586397, -0.74669512, -0.74902649,
|
||||
-0.75342964, -0.76598043],
|
||||
},
|
||||
{'name': 'sparseDM',
|
||||
'rv': [25, 30, 35, 40, 45, 50, 55, 60],
|
||||
'rs': [0.78351117, 0.79751047, 0.8225573 , 0.83751894, 0.85443167,
|
||||
0.86346031, 0.85692501, 0.91470448],
|
||||
'dc': [-0.67407548, -0.62389586, -0.59125414, -0.55341724, -0.54659457,
|
||||
-0.5297821 , -0.534683 , -0.51055946],
|
||||
},
|
||||
{'name': 'denseHalos',
|
||||
'rv': [15, 20, 25, 30, 35, 40, 45, 50, 55],
|
||||
'rs': [0.75393528, 0.7758442 , 0.79720886, 0.81560553, 0.83797299,
|
||||
0.84377082, 0.84900783, 0.8709897 , 0.86886687],
|
||||
'dc': [-0.81348968, -0.77362777, -0.74336192, -0.72571135, -0.67928029,
|
||||
-0.6279349 , -0.6313316 , -0.55188564, -0.48096026],
|
||||
},
|
||||
{'name': 'sparseHalos',
|
||||
'rv': [25, 30, 35, 40, 45, 50, 55, 60, 65, 70],
|
||||
'rs': [0.76420703, 0.78939067, 0.80480265, 0.82315275, 0.8158607 ,
|
||||
0.82553517, 0.83843323, 0.85759226, 0.8471268 , 0.89286939],
|
||||
'dc': [-0.79317192, -0.81661415, -0.76770778, -0.7151494 , -0.718561 ,
|
||||
-0.70858856, -0.68995608, -0.67415305, -0.63706798, -0.5303759],
|
||||
},
|
||||
{'name': 'denseGal',
|
||||
'rv': [10, 15, 20, 25, 30, 35, 40, 45],
|
||||
'rs': [0.70048139, 0.73717884, 0.75338516, 0.76782043, 0.79292536,
|
||||
0.80157122, 0.8207239 , 0.8091386],
|
||||
'dc': [-0.83166549, -0.86505329, -0.81066899, -0.7662453 , -0.72840363,
|
||||
-0.65163607, -0.57937656, -0.57125164],
|
||||
},
|
||||
{'name': 'sparseGal',
|
||||
'rv': [25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75],
|
||||
'rs': [0.75928922, 0.76622648, 0.77695425, 0.79963152, 0.8045125 ,
|
||||
0.81892965, 0.83439691, 0.86600085, 0.83166875, 0.85283258,
|
||||
0.83971344],
|
||||
'dc': [-0.82413212, -0.87483536, -0.8221596 , -0.78459706, -0.75290061,
|
||||
-0.77513988, -0.70012913, -0.67487994, -0.69903308, -0.65811992,
|
||||
-0.57929526],
|
||||
},
|
||||
]
|
||||
|
||||
mySample = next((item for item in samples if item['name'] == density), None)
|
||||
if mySample == None:
|
||||
print("Sample", density," not found! Use one of ", [item['name'] for item in samples])
|
||||
return
|
||||
|
||||
# interpolate the radii
|
||||
rsFunc = interp1d( mySample['rv'], mySample['rs'], kind='cubic' )
|
||||
dcFunc = interp1d( mySample['rv'], mySample['dc'], kind='cubic' )
|
||||
|
||||
rs = rsFunc(radius)
|
||||
dc = dcFunc(radius)
|
||||
|
||||
# return best-fits
|
||||
rVals = np.linspace(0.0, 3*radius, 100) / radius
|
||||
return (rs,dc), rVals*radius, HSWProfile(rVals,rs,dc)
|
||||
|
147
python_source/vide/voidUtil/xcorUtil.py
Normal file
147
python_source/vide/voidUtil/xcorUtil.py
Normal file
|
@ -0,0 +1,147 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/voidUtil/xcorUtil.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.cm as cm
|
||||
from matplotlib import rc
|
||||
from . import xcorlib
|
||||
from vide.voidUtil import getArray
|
||||
|
||||
def computeXcor(catalog,
|
||||
figDir="./",
|
||||
Nmesh = 256,
|
||||
Nbin = 100
|
||||
):
|
||||
|
||||
# Computes and plots void-void and void-matter(galaxy) correlations
|
||||
# catalog: catalog to analyze
|
||||
# figDir: where to place plots
|
||||
# Nmesh: number of grid cells in cic mesh-interpolation
|
||||
# Nbin: number of bins in final plots
|
||||
|
||||
# Parameters
|
||||
Lbox = catalog.boxLen[0] # Boxlength
|
||||
Lboxcut = 0.
|
||||
Lbox -= 2*Lboxcut
|
||||
|
||||
# Input particle arrays of shape (N,3)
|
||||
xm = catalog.partPos # Halos / Galaxies / Dark matter
|
||||
xv = getArray(catalog.voids, 'macrocenter')
|
||||
|
||||
|
||||
# Interpolate to mesh
|
||||
dm, wm, ws = xcorlib.cic(xm, Lbox, Lboxcut = Lboxcut, Nmesh = Nmesh, weights = None)
|
||||
dv, wm, ws = xcorlib.cic(xv, Lbox, Lboxcut = Lboxcut, Nmesh = Nmesh, weights = None)
|
||||
|
||||
# Fourier transform
|
||||
dmk = np.fft.rfftn(dm)
|
||||
dvk = np.fft.rfftn(dv)
|
||||
|
||||
# 1D Power spectra & correlation functions
|
||||
((Nm, km, Pmm, SPmm),(Nmx, rm, Xmm, SXmm)) = xcorlib.powcor(dmk, dmk, Lbox, Nbin, 'lin', True, True, 1)
|
||||
((Nm, km, Pvm, SPvm),(Nmx, rm, Xvm, SXvm)) = xcorlib.powcor(dvk, dmk, Lbox, Nbin, 'lin', True, True, 1)
|
||||
((Nm, km, Pvv, SPvv),(Nmx, rm, Xvv, SXvv)) = xcorlib.powcor(dvk, dvk, Lbox, Nbin, 'lin', True, True, 1)
|
||||
|
||||
# Number densities
|
||||
nm = np.empty(len(km))
|
||||
nv = np.empty(len(km))
|
||||
nm[:] = len(xm)/Lbox**3
|
||||
nv[:] = len(xv)/Lbox**3
|
||||
|
||||
|
||||
# Plots
|
||||
mpl.rc('font', family='serif')
|
||||
ms = 2.5
|
||||
fs = 16
|
||||
mew = 0.1
|
||||
margin = 1.2
|
||||
kmin = km.min()/margin
|
||||
kmax = km.max()*margin
|
||||
rmin = rm.min()/margin
|
||||
rmax = rm.max()*margin
|
||||
|
||||
|
||||
# Density fields (projected)
|
||||
plt.imshow(np.sum(dm[:,:,:]+1,2),extent=[0,Lbox,0,Lbox],aspect='equal',cmap='YlGnBu_r',interpolation='gaussian')
|
||||
plt.xlabel(r'$x \;[h^{-1}\mathrm{Mpc}]$')
|
||||
plt.ylabel(r'$y \;[h^{-1}\mathrm{Mpc}]$')
|
||||
plt.title(r'Dark matter')
|
||||
plt.savefig(figDir+'/dm.eps', bbox_inches="tight")
|
||||
plt.savefig(figDir+'/dm.pdf', bbox_inches="tight")
|
||||
plt.savefig(figDir+'/dm.png', bbox_inches="tight")
|
||||
plt.clf()
|
||||
|
||||
plt.imshow(np.sum(dv[:,:,:]+1,2)/Nmesh,extent=[0,Lbox,0,Lbox],aspect='equal',cmap='YlGnBu_r',interpolation='gaussian')
|
||||
plt.xlabel(r'$x \;[h^{-1}\mathrm{Mpc}]$')
|
||||
plt.ylabel(r'$y \;[h^{-1}\mathrm{Mpc}]$')
|
||||
plt.title(r'Voids')
|
||||
plt.savefig(figDir+'/dv.eps', bbox_inches="tight") #, dpi=300
|
||||
plt.savefig(figDir+'/dv.pdf', bbox_inches="tight") #, dpi=300
|
||||
plt.savefig(figDir+'/dv.png', bbox_inches="tight") #, dpi=300
|
||||
plt.clf()
|
||||
|
||||
|
||||
# Power spectra & correlation functions
|
||||
pa ,= plt.plot(km, Pmm, 'k-o', ms=0.8*ms, mew=mew, mec='k')
|
||||
#plt.plot(km, Pmm-1./nm, 'k--', ms=ms, mew=mew)
|
||||
plt.fill_between(km, Pmm+SPmm, abs(Pmm-SPmm), color='k', alpha=0.2)
|
||||
pb ,= plt.plot(km, Pvm, 'm-D', ms=ms, mew=mew, mec='k')
|
||||
plt.plot(km, -Pvm, 'mD', ms=ms, mew=mew, mec='k')
|
||||
plt.fill_between(km, abs(Pvm+SPvm), abs(Pvm-SPvm), color='m', alpha=0.2)
|
||||
pc ,= plt.plot(km, Pvv, 'b-p', ms=1.3*ms, mew=mew, mec='k')
|
||||
#plt.plot(km, Pvv-1./nv, 'b--', ms=ms, mew=mew)
|
||||
plt.fill_between(km, Pvv+SPvv, abs(Pvv-SPvv), color='b', alpha=0.2)
|
||||
plt.xlabel(r'$k \;[h\mathrm{Mpc}^{-1}]$')
|
||||
plt.ylabel(r'$P(k) \;[h^{-3}\mathrm{Mpc}^3]$')
|
||||
plt.title(r'Power spectra')
|
||||
plt.xscale('log')
|
||||
plt.yscale('log')
|
||||
plt.xlim(kmin,kmax)
|
||||
plt.ylim(10**np.floor(np.log10(abs(Pvm[1:]).min()))/margin, max(10**np.ceil(np.log10(Pmm.max())),10**np.ceil(np.log10(Pvv.max())))*margin)
|
||||
plt.legend([pa, pb, pc],['tt', 'vt', 'vv'],'best',prop={'size':12})
|
||||
plt.savefig(figDir+'/power.eps', bbox_inches="tight")
|
||||
plt.savefig(figDir+'/power.pdf', bbox_inches="tight")
|
||||
plt.savefig(figDir+'/power.png', bbox_inches="tight")
|
||||
plt.clf()
|
||||
|
||||
pa ,= plt.plot(rm, Xmm, 'k-o', ms=0.8*ms, mew=mew)
|
||||
plt.fill_between(rm, abs(Xmm+SXmm), abs(Xmm-SXmm), color='k', alpha=0.2)
|
||||
pb ,= plt.plot(rm, Xvm, 'm-D', ms=ms, mew=mew)
|
||||
plt.plot(rm, -Xvm, 'mD', ms=ms, mew=mew)
|
||||
plt.fill_between(rm, abs(Xvm+SXvm), abs(Xvm-SXvm), color='m', alpha=0.2)
|
||||
pc ,= plt.plot(rm, Xvv, 'b-p', ms=1.3*ms, mew=mew)
|
||||
plt.plot(rm, -Xvv, 'bp', ms=ms, mew=1.3*mew)
|
||||
plt.fill_between(rm, abs(Xvv+SXvv), abs(Xvv-SXvv), color='b', alpha=0.2)
|
||||
plt.xlabel(r'$r \;[h^{-1}\mathrm{Mpc}]$')
|
||||
plt.ylabel(r'$\xi(r)$')
|
||||
plt.title(r'Correlation functions')
|
||||
plt.xscale('log')
|
||||
plt.yscale('log')
|
||||
plt.xlim(rmin,rmax)
|
||||
plt.ylim(min(10**np.floor(np.log10(abs(Xvm).min())),10**np.floor(np.log10(abs(Xmm).min())))/margin, max(10**np.ceil(np.log10(Xmm.max())),10**np.ceil(np.log10(Xvv.max())))*margin)
|
||||
plt.legend([pa, pb, pc],['tt', 'vt', 'vv'],'best',prop={'size':12})
|
||||
plt.savefig(figDir+'/correlation.eps', bbox_inches="tight")
|
||||
plt.savefig(figDir+'/correlation.pdf', bbox_inches="tight")
|
||||
plt.savefig(figDir+'/correlation.png', bbox_inches="tight")
|
||||
plt.clf()
|
||||
|
||||
|
||||
return
|
107
python_source/vide/voidUtil/xcorlib.py
Normal file
107
python_source/vide/voidUtil/xcorlib.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/vide/voidUtil/xcorlib.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
import numpy as np
|
||||
|
||||
# CIC interpolation
|
||||
def cic(x, Lbox, Lboxcut = 0, Nmesh = 128, weights = None):
|
||||
|
||||
if weights == None: weights = 1
|
||||
wm = np.mean(weights)
|
||||
ws = np.mean(weights**2)
|
||||
|
||||
d = np.mod(x/(Lbox+2*Lboxcut)*Nmesh,1)
|
||||
|
||||
box = ([Lboxcut,Lbox+Lboxcut],[Lboxcut,Lbox+Lboxcut],[Lboxcut,Lbox+Lboxcut])
|
||||
|
||||
rho = np.histogramdd(x, range = box, bins = Nmesh, weights = weights*(1-d[:,0])*(1-d[:,1])*(1-d[:,2]))[0] \
|
||||
+ np.roll(np.histogramdd(x, range = box, bins = Nmesh, weights = weights*d[:,0]*(1-d[:,1])*(1-d[:,2]))[0],1,0) \
|
||||
+ np.roll(np.histogramdd(x, range = box, bins = Nmesh, weights = weights*(1-d[:,0])*d[:,1]*(1-d[:,2]))[0],1,1) \
|
||||
+ np.roll(np.histogramdd(x, range = box, bins = Nmesh, weights = weights*(1-d[:,0])*(1-d[:,1])*d[:,2])[0],1,2) \
|
||||
+ np.roll(np.roll(np.histogramdd(x, range = box, bins = Nmesh, weights = weights*d[:,0]*d[:,1]*(1-d[:,2]))[0],1,0),1,1) \
|
||||
+ np.roll(np.roll(np.histogramdd(x, range = box, bins = Nmesh, weights = weights*d[:,0]*(1-d[:,1])*d[:,2])[0],1,0),1,2) \
|
||||
+ np.roll(np.roll(np.histogramdd(x, range = box, bins = Nmesh, weights = weights*(1-d[:,0])*d[:,1]*d[:,2])[0],1,1),1,2) \
|
||||
+ np.roll(np.roll(np.roll(np.histogramdd(x, range = box, bins = Nmesh, weights = weights*d[:,0]*d[:,1]*d[:,2])[0],1,0),1,1),1,2)
|
||||
|
||||
rho /= wm
|
||||
|
||||
rho = rho/rho.mean() - 1.
|
||||
|
||||
return (rho, wm, ws)
|
||||
|
||||
|
||||
# Power spectra & correlation functions
|
||||
def powcor(d1, d2, Lbox, Nbin = 10, scale = 'lin', cor = False, cic = True, dim = 1):
|
||||
|
||||
Nmesh = len(d1)
|
||||
|
||||
# CIC correction
|
||||
if cic:
|
||||
wid = np.indices(np.shape(d1))
|
||||
wid[np.where(wid >= Nmesh/2)] -= Nmesh
|
||||
wid = wid*np.pi/Nmesh + 1e-100
|
||||
wcic = np.prod(np.sin(wid)/wid,0)**2
|
||||
|
||||
# Shell average power spectrum
|
||||
dk = 2*np.pi/Lbox
|
||||
Pk = np.conj(d1)*d2*(Lbox/Nmesh**2)**3
|
||||
if cic: Pk /= wcic**2
|
||||
|
||||
(Nm, km, Pkm, SPkm) = shellavg(np.real(Pk), dk, Nmesh, Nbin = Nbin, xmin = 0., xmax = Nmesh*dk/2, scale = scale, dim = dim)
|
||||
|
||||
# Inverse Fourier transform and shell average correlation function
|
||||
if cor:
|
||||
if cic: Pk *= wcic**2 # Undo cic-correction in correlation function
|
||||
dx = Lbox/Nmesh
|
||||
Xr = np.fft.irfftn(Pk)*(Nmesh/Lbox)**3
|
||||
|
||||
(Nmx, rm, Xrm, SXrm) = shellavg(np.real(Xr), dx, Nmesh, Nbin = Nbin/2, xmin = dx, xmax = 140., scale = scale, dim = dim)
|
||||
|
||||
return ((Nm, km, Pkm, SPkm),(Nmx, rm, Xrm, SXrm))
|
||||
|
||||
else: return (Nm, km, Pkm, SPkm)
|
||||
|
||||
|
||||
# Shell averaging
|
||||
def shellavg(f, dx, Nmesh, Nbin = 10, xmin = 0., xmax = 1., scale = 'lin', dim = 1):
|
||||
|
||||
x = np.indices(np.shape(f))
|
||||
x[np.where(x >= Nmesh/2)] -= Nmesh
|
||||
f = f.flatten()
|
||||
|
||||
if scale == 'lin': bins = xmin+(xmax-xmin)* np.linspace(0,1,Nbin+1)
|
||||
if scale == 'log': bins = xmin*(xmax/xmin)**np.linspace(0,1,Nbin+1)
|
||||
|
||||
if dim == 1: # 1D
|
||||
x = dx*np.sqrt(np.sum(x**2,0)).flatten()
|
||||
Nm = np.histogram(x, bins = bins)[0]
|
||||
xm = np.histogram(x, bins = bins, weights = x)[0]/Nm
|
||||
fm = np.histogram(x, bins = bins, weights = f)[0]/Nm
|
||||
fs = np.sqrt((np.histogram(x, bins = bins, weights = f**2)[0]/Nm - fm**2)/(Nm-1))
|
||||
return (Nm, xm, fm, fs)
|
||||
|
||||
elif dim == 2: # 2D
|
||||
xper = dx*np.sqrt(x[0,:,:,:]**2 + x[1,:,:,:]**2 + 1e-100).flatten()
|
||||
xpar = dx*np.abs(x[2,:,:,:]).flatten()
|
||||
x = dx*np.sqrt(np.sum(x**2,0)).flatten()
|
||||
Nm = np.histogram2d(xper, xpar, bins = [bins,bins])[0]
|
||||
xmper = np.histogram2d(xper, xpar, bins = [bins,bins], weights = xper)[0]/Nm
|
||||
xmpar = np.histogram2d(xper, xpar, bins = [bins,bins], weights = xpar)[0]/Nm
|
||||
fm = np.histogram2d(xper, xpar, bins = [bins,bins], weights = f)[0]/Nm
|
||||
return (Nm, xmper, xmpar, fm)
|
0
python_source/void_pipeline/__init__.py
Normal file
0
python_source/void_pipeline/__init__.py
Normal file
140
python_source/void_pipeline/__main__.py
Normal file
140
python_source/void_pipeline/__main__.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
#!/usr/bin/env python
|
||||
#+
|
||||
# VIDE -- Void IDentification and Examination -- ./python_tools/void_pipeline/__init__.py
|
||||
# Copyright (C) 2010-2014 Guilhem Lavaux
|
||||
# Copyright (C) 2011-2014 P. M. Sutter
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#+
|
||||
|
||||
# Stage 1 : prepare particles for void finding
|
||||
# Stage 2 : find voids
|
||||
# Stage 3 : prune catalog
|
||||
|
||||
from vide.backend import *
|
||||
import vide
|
||||
import imp
|
||||
import os
|
||||
import pickle
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
if (len(sys.argv) == 1):
|
||||
print("Usage: python3 -m void_pipeline parameter_file.py")
|
||||
exit(-1)
|
||||
|
||||
if (len(sys.argv) > 1):
|
||||
filename = sys.argv[1]
|
||||
print(" Loading parameters from", filename)
|
||||
if not os.access(filename, os.F_OK):
|
||||
print(" Cannot find parameter file %s!" % filename)
|
||||
exit(-1)
|
||||
parms = imp.load_source("name", filename)
|
||||
regenerateFlag = False
|
||||
globals().update(vars(parms))
|
||||
void_path = os.path.split(vide.__file__)[0]
|
||||
ZOBOV_PATH=f'{void_path}/bin/'
|
||||
CTOOLS_PATH=ZOBOV_PATH
|
||||
print(f"ZOBOV_PATH is {ZOBOV_PATH}")
|
||||
else:
|
||||
print(" Using default parameters")
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
if not os.access(logDir, os.F_OK):
|
||||
os.makedirs(logDir)
|
||||
|
||||
if not os.access(figDir, os.F_OK):
|
||||
os.makedirs(figDir)
|
||||
|
||||
if not continueRun:
|
||||
print(" Cleaning out log files...")
|
||||
|
||||
if startCatalogStage <= 1 and glob.glob(logDir+"/generate*") != []:
|
||||
os.system("rm %s/generate*" % logDir)
|
||||
if startCatalogStage <= 2 and glob.glob(logDir+"/zobov*") != []:
|
||||
os.system("rm %s/zobov*" % logDir)
|
||||
if startCatalogStage <= 3 and glob.glob(logDir+"/prune*") != []:
|
||||
os.system("rm %s/prune*" % logDir)
|
||||
|
||||
for sample in dataSampleList:
|
||||
|
||||
sampleName = sample.fullName
|
||||
|
||||
print(" Working with data set", sampleName, "...")
|
||||
zobovDir = workDir+"/sample_"+sampleName+"/"
|
||||
sample.zobovDir = zobovDir
|
||||
|
||||
if not os.access(zobovDir, os.F_OK):
|
||||
os.makedirs(zobovDir)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
if (startCatalogStage <= 1) and (endCatalogStage >= 1) and not sample.isCombo:
|
||||
print(" Extracting tracers from catalog...", end=' ')
|
||||
sys.stdout.flush()
|
||||
|
||||
logFile = logDir+"/generate_"+sampleName+".out"
|
||||
|
||||
if sample.dataType == "observation":
|
||||
GENERATE_PATH = CTOOLS_PATH+"/prepObservation"
|
||||
else:
|
||||
GENERATE_PATH = CTOOLS_PATH+"/prepSimulation"
|
||||
|
||||
launchPrep(sample, GENERATE_PATH, workDir=workDir,
|
||||
inputDataDir=inputDataDir, zobovDir=zobovDir,
|
||||
figDir=figDir, logFile=logFile, useComoving=sample.useComoving,
|
||||
continueRun=continueRun, regenerate=regenerateFlag)
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
if (startCatalogStage <= 2) and (endCatalogStage >= 2) and not sample.isCombo:
|
||||
print(" Extracting voids with ZOBOV...", end=' ')
|
||||
sys.stdout.flush()
|
||||
|
||||
launchZobov(sample, ZOBOV_PATH, zobovDir=zobovDir, logDir=logDir,
|
||||
continueRun=continueRun, numZobovDivisions=numZobovDivisions,
|
||||
numZobovThreads=numZobovThreads, mergingThreshold=mergingThreshold)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
if (startCatalogStage <= 3) and (endCatalogStage >= 3) and not sample.isCombo:
|
||||
|
||||
print(" Pruning void catalogs", "...", end=' ')
|
||||
sys.stdout.flush()
|
||||
|
||||
logFile = logDir+"/pruneVoids_"+sampleName+".out"
|
||||
|
||||
PRUNE_PATH = CTOOLS_PATH+"/pruneVoids"
|
||||
|
||||
launchPrune(sample, PRUNE_PATH,
|
||||
logFile=logFile, zobovDir=zobovDir,
|
||||
useComoving=sample.useComoving, continueRun=continueRun, mergingThreshold=mergingThreshold)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
if (startCatalogStage <= 4) and (endCatalogStage >= 4):
|
||||
|
||||
print(" Plotting...", end=' ')
|
||||
sys.stdout.flush()
|
||||
|
||||
#for thisDataPortion in dataPortions:
|
||||
#plotRedshiftDistribution(workDir, dataSampleList, figDir, showPlot=False,
|
||||
# dataPortion=thisDataPortion, setName=setName)
|
||||
#plotSizeDistribution(workDir, dataSampleList, figDir, showPlot=False,
|
||||
# dataPortion=thisDataPortion, setName=setName)
|
||||
#plotNumberDistribution(workDir, dataSampleList, figDir, showPlot=False,
|
||||
# dataPortion=thisDataPortion, setName=setName)
|
||||
#plotVoidDistribution(workDir, dataSampleList, figDir, showPlot=False,
|
||||
# dataPortion=thisDataPortion, setName=setName)
|
||||
|
||||
print("\n Done!")
|
Loading…
Add table
Add a link
Reference in a new issue