; docformat = 'rst' ;+ ; This procedure calculates the 1/Vmax bivariate brightness ; distribution from input arrays of two quantities (e.g., absolute ; magnitude and surface brightness) and weights (e.g., 1/Vmax) ;- ;+ ; This procedure calculates the 1/Vmax bivariate brightness ; distribution from input arrays of two quantities (e.g., absolute ; magnitude and surface brightness) and weights (e.g., 1/Vmax) ; ; Bins in each dimension must have equal width ; ; :Returns: fltarr/dblarr ; Returns phi, value of space density ; :Params: ; m1 : in, required ; m2 : in, required ; weights : in, optional ; E.g., 1./Vmax. Set to single value to give all galaxies the ; same weight, or leave empty to give all galaxies a weight of 1. ; :Keywords: ; bincentres1 : in, out, optional ; Centre of each bin in m1 ; bincentres2 : in, out, optional ; Centre of each bin in m2 ; err_phi : out, optional ; Poisson errors = phi / sqrt(n) ; ninbin : out, optional ; Number of galaxies in each bin ; nbins1 : in, optional ; Number of bins in m1 (ignored if bincentres set) ; nbins2 : in, optional ; Number of bins in m2 (ignored if bincentres set) ; xrange : in, optional ; Minimum and maximum m1 (ignored if bincentres1 set) ; yrange : in, optional ; Minimum and maximum m2 (ignored if bincentres2 set) ; jackknife : in, optional ; Integer for each galaxy giving the jackknife region in which ; the galaxy lies ; choloniewski : in, out, optional ; Choloniewski fit ; chol_xrange : in, optional, type=fltarr(2) ; xrange for Choloniewski fit (ajs_choloniewski_fit) ; chol_yrange : in, optional, type=fltarr(2) ; yrange for Choloniewski fit (ajs_choloniewski_fit) ; cov_mat : out, optional ; Covariance matrix of Choloniewski fit ; vars : in, optional ; See ajs_choloniewski_fit ; zmin : in, optional ; See ajs_choloniewski_fit ; zmax : in, optional ; See ajs_choloniewski_fit ; area : in, optional ; See ajs_choloniewski_fit ; q0 : in, optional ; See ajs_choloniewski_fit ; q1 : in, optional ; See ajs_choloniewski_fit ; :History: ; 6 Mar 2008 Created (Anthony Smith) ; ; 18 Mar 2008 Added jackknife ; ; 7 Apr 2008 Added jackknife Choloniewski fit ;- FUNCTION ajs_vmax_bbd, m1, m2, weights, bincentres1=bincentres1, $ bincentres2=bincentres2, $ err_phi=err_phi, ninbin=ninbin, nbins1=nbins1, $ nbins2=nbins2, xrange=xrange, yrange=yrange, $ jackknife=jackknife, $ choloniewski=choloniewski, chol_xrange=chol_xrange, $ chol_yrange=chol_yrange, cov_mat=cov_mat, $ vars=vars, zmin=zmin, zmax=zmax, area=area, q0=q0, q1=q1 compile_opt idl2 debug = ajs_debug() IF debug GE 1 THEN BEGIN message, 'Estimating 1/Vmax BBD', /inf message, ajs_kw_string(nbins1=nbins1, nbins2=nbins2, xrange=xrange, $ yrange=yrange, choloniewski=choloniewski, $ chol_xrange=chol_xrange, $ chol_yrange=chol_yrange, $ zmin=zmin, zmax=zmax, area=area, q0=q0, q1=q1), $ /inf ENDIF ;; Preliminaries IF n_elements(weights) EQ 1 THEN $ weights = replicate(weights, n_elements(m1)) $ ELSE IF n_elements(weights) EQ 0 THEN $ weights = replicate(1, n_elements(m1)) IF n_elements(bincentres1) EQ 0 THEN BEGIN IF n_elements(nbins1) EQ 0 THEN $ nbins1 = 24 IF n_elements(xrange) GT 0 THEN $ ;; bincentres1 = ajs_linspace(max([min(xrange), min(m1)]), $ ;; min([max(xrange), max(m1) + 1d-5]), $ bincentres1 = ajs_linspace(min(xrange), max(xrange), $ nbins1, $ /bincentres) $ ELSE $ bincentres1 = ajs_linspace(min(m1), max(m1) + 1e-6, nbins1, $ /bincentres) ENDIF IF n_elements(bincentres2) EQ 0 THEN BEGIN IF n_elements(nbins2) EQ 0 THEN $ nbins2 = 24 IF n_elements(yrange) GT 0 THEN $ ;; bincentres2 = ajs_linspace(max([min(yrange), min(m2)]), $ ;; min([max(yrange), max(m2) + 1d-5]), $ bincentres2 = ajs_linspace(min(yrange), max(yrange), $ nbins2, $ /bincentres) $ ELSE $ bincentres2 = ajs_linspace(min(m2), max(m2) + 1d-5, nbins2, $ /bincentres) ENDIF binsize1 = (max(bincentres1) - min(bincentres1)) $ / (n_elements(bincentres1) - 1) m1_min = min(bincentres1) - binsize1 / 2. m1_max = max(bincentres1) + binsize1 / 2. - 1d-5 binsize2 = (max(bincentres2) - min(bincentres2)) $ / (n_elements(bincentres2) - 1) m2_min = min(bincentres2) - binsize2 / 2. m2_max = max(bincentres2) + binsize2 / 2. - 1d-5 ;; Do the whole thing whether or not jackknife is going to be done incl = where(m1 GE m1_min AND m1 LE m1_max $ AND m2 GT m2_min AND m2 LE m2_max) phi = hist2d(m1[incl], m2[incl], weights[incl], $ min1=m1_min, max1=m1_max, $ binsize1=binsize1, obin1=obin1, omin1=omin1, omax1=omax1, $ min2=m2_min, max2=m2_max, $ binsize2=binsize2, obin2=obin2, omin2=omin2, omax2=omax2, $ density=ninbin) / binsize1 / binsize2 err_phi = phi / sqrt(ninbin) IF arg_present(choloniewski) THEN BEGIN choloniewski = ajs_choloniewski_fit(bincentres1, bincentres2, $ phi, err_phi, $ xrange=chol_xrange, $ yrange=chol_yrange, vars=vars, $ zmin=zmin, zmax=zmax, area=area, $ q0=q0, q1=q1, cov_mat=cov_mat) ENDIF ;; Check okay IF n_elements(obin1) NE n_elements(bincentres1) $ OR n_elements(obin2) NE n_elements(bincentres2) THEN $ message, 'Conflicting bins' IF total(ninbin) NE n_elements(incl) THEN $ message, 'Different total number after making histogram' IF n_elements(jackknife) GT 0 THEN BEGIN IF debug GE 1 THEN message, 'Using jackknife resampling', /inf ;; Original (full) sample phi_orig = phi err_phi_orig = err_phi ninbin_orig = ninbin IF arg_present(choloniewski) THEN $ choloniewski_orig = choloniewski ;; Prepare for jackknife resampling min_jack = min(jackknife) n_jack = max(jackknife) - min_jack + 1 phi_arr = dblarr(n_elements(bincentres1), n_elements(bincentres2), $ n_jack) ninbin_arr = dblarr(n_elements(bincentres1), n_elements(bincentres2), $ n_jack) IF arg_present(choloniewski) THEN $ choloniewski_arr = dblarr(6, n_jack) ;; Results excluding each jackknife sample in turn FOR i = 0, n_jack - 1 DO BEGIN IF debug GE 2 THEN message, 'Jackknife ' + string(i), /inf incl = where(m1 GE m1_min AND m1 LE m1_max $ AND m2 GT m2_min AND m2 LE m2_max $ AND jackknife NE i + min_jack, n_current) phi_arr[*, *, i] = $ hist2d(m1[incl], m2[incl], weights[incl], $ min1=m1_min, max1=m1_max, $ binsize1=binsize1, obin1=obin1, omin1=omin1, omax1=omax1, $ min2=m2_min, max2=m2_max, $ binsize2=binsize2, obin2=obin2, omin2=omin2, omax2=omax2, $ density=ninbin) / binsize1 / binsize2 $ ;; NB weights adjusted according to no. of galaxies ;; If equal area: * n_jack / (n_jack - 1) * n_elements(m1) / n_current ;; NB original err_phi may have been altered by chol. fit to ;; supply values for empty bins: don't want to do ;; that every time! err_phi_tmp = phi_arr[*, *, i] / sqrt(ninbin) no_err = where(err_phi_tmp LE 0 OR finite(err_phi_tmp, /nan), $ n_no_err) IF n_no_err GT 0 THEN $ err_phi_tmp[no_err] = err_phi_orig[no_err] $ * sqrt(total(ninbin_orig) / total(ninbin)) ninbin_arr[*, *, i] = ninbin IF arg_present(choloniewski) THEN BEGIN choloniewski_arr[*, i] = $ ajs_choloniewski_fit(bincentres1, bincentres2, $ phi_arr[*, *, i], err_phi_tmp, $ xrange=chol_xrange, $ yrange=chol_yrange, vars=vars, $ zmin=zmin, zmax=zmax, area=area, $ q0=q0, q1=q1) ENDIF ENDFOR ;; Jackknife quantities phi = dblarr(n_elements(bincentres1), n_elements(bincentres2)) err_phi = dblarr(n_elements(bincentres1), n_elements(bincentres2)) FOR i = 0, n_elements(bincentres1) - 1 DO BEGIN FOR j = 0, n_elements(bincentres2) - 1 DO BEGIN err_phi[i, j] = ajs_jackknife(phi_arr[i, j, *], $ bias_correction=bc_tmp, $ original_estimate=phi_orig[i, j]) phi[i, j] = phi_orig[i, j] + bc_tmp ;; err_phi[i, j] = ajs_jackknife(phi_arr[i, j, *], $ ;; jackknife_mean=phi_tmp) ;; phi[i, j] = phi_tmp ENDFOR ;; No zero errors zeros = where(err_phi EQ 0, n_zeros) IF n_zeros GT 0 THEN $ err_phi[zeros] = err_phi_orig[zeros] ENDFOR IF arg_present(choloniewski) THEN BEGIN choloniewski = dblarr(6) cov_mat = ajs_jackknife(choloniewski_arr, bias_correction=bc_tmp, $ original_estimate=choloniewski_orig) choloniewski = choloniewski_orig + bc_tmp ENDIF ;; Number in each bin (no jackknife) ninbin = ninbin_orig ;; incl = where(m1 GE m1_min AND m1 LE m1_max $ ;; AND m2 GT m2_min AND m2 LE m2_max) ;; ninbin = $ ;; hist2d(m1[incl], m2[incl], $ ;; min1=m1_min, max1=m1_max, $ ;; binsize1=binsize1, obin1=obin1, omin1=omin1, omax1=omax1, $ ;; min2=m2_min, max2=m2_max, $ ;; binsize2=binsize2, obin2=obin2, omin2=omin2, omax2=omax2) ENDIF ;ELSE BEGIN ;; incl = where(m1 GE m1_min AND m1 LE m1_max $ ;; AND m2 GT m2_min AND m2 LE m2_max) ;; phi = hist2d(m1[incl], m2[incl], weights[incl], $ ;; min1=m1_min, max1=m1_max, $ ;; binsize1=binsize1, obin1=obin1, omin1=omin1, omax1=omax1, $ ;; min2=m2_min, max2=m2_max, $ ;; binsize2=binsize2, obin2=obin2, omin2=omin2, omax2=omax2, $ ;; density=ninbin) / binsize1 / binsize2 ;; err_phi = phi / sqrt(ninbin) ;; ENDELSE IF debug GE 1 THEN $ message, 'Total number of galaxies: ' + strtrim(total(ninbin), 2), /inf ;; empty_bins = where(ninbin EQ 0, nempty) ;; IF nempty GT 0 THEN BEGIN ;; phi[empty_bins] = 0 ;; err_phi[empty_bins] = !values.f_nan ;; ENDIF return, phi END ;+ ; Test ajs_vmax_lf ;- PRO ajs_vmax_bbd_test compile_opt idl2 m1 = ajs_linspace(-26, -16, 50) m2 = ajs_linspace(14, 24, 50) weights = intarr(n_elements(m1)) + 1e-6 phi = ajs_vmax_bbd(m1, m2, weights, nbins1=30, nbins2=30, ninbin=ninbin) print, phi print, total(ninbin) END