def getUSCensusAgeDist(): """ Get US Census Age Distribution """ t_num = _INDVCMF_DATA['USCensus2010population'] list_AgeCensus = t_num[0] freq_AgeCensus = np.round( t_num[1] / 1000 ) # Reduce # of populations to manageable number, this doesn't change probability # Remove age < 10 and 70 < age: freq_AgeCensus[:10] = 0 freq_AgeCensus[71:] = 0 list_Age = [] for k in range(len(list_AgeCensus)): list_Age = np.hstack( (list_Age, np.repeat(list_AgeCensus[k], freq_AgeCensus[k]))) return list_Age
def genMonteCarloObs(n_obs=1, fieldsize=10, list_Age=[32], out='LMS', wl=None, allow_negative_values=False): """ Monte-Carlo generation of individual observer cone fundamentals. Args: :n_obs: | 1, optional | Number of observer CMFs to generate. :list_Age: | list of observer ages or str, optional | Defaults to 32 (cfr. CIE2006 CMFs) | If 'us_census': use US population census of 2010 to generate list_Age. :fieldsize: | fieldsize in degrees (between 2° and 10°), optional | Defaults to 10°. :out: | 'LMS' or str, optional | Determines output. :wl: | None, optional | Interpolation/extraplation of :LMS: output to specified wavelengths. | None: output original _WL = np.array([390,780,5]) :allow_negative_values: | False, optional | Cone fundamentals or color matching functions | should not have negative values. | If False: X[X<0] = 0. Returns: :returns: | LMS [,var_age, vAll] | - LMS: ndarray with population LMS functions. | - var_age: ndarray with population observer ages. | - vAll: dict with population physiological factors (see .keys()) References: 1. `Asano Y, Fairchild MD, and Blondé L (2016). Individual Colorimetric Observer Model. PLoS One 11, 1–19. <http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0145671>`_ 2. `Asano Y, Fairchild MD, Blondé L, and Morvan P (2016). Color matching experiment for highlighting interobserver variability. Color Res. Appl. 41, 530–539. <https://onlinelibrary.wiley.com/doi/abs/10.1002/col.21975>`_ 3. `CIE, and CIE (2006). Fundamental Chromaticity Diagram with Physiological Axes - Part I (Vienna: CIE). <http://www.cie.co.at/publications/fundamental-chromaticity-diagram-physiological-axes-part-1>`_ 4. `Asano's Individual Colorimetric Observer Model <https://www.rit.edu/cos/colorscience/re_AsanoObserverFunctions.php>`_ """ # Scale down StdDev by scalars optimized using Asano's 75 observers # collected in Germany: stdDevAllParam = _INDVCMF_STD_DEV_ALL_PARAM.copy() scale_factors = [0.98, 0.98, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5] scale_factors = dict(zip(list(stdDevAllParam.keys()), scale_factors)) stdDevAllParam = { k: v * scale_factors[k] for (k, v) in stdDevAllParam.items() } # Get Normally-distributed Physiological Factors: vAll = getMonteCarloParam(n_obs=n_obs) if list_Age is 'us_census': list_Age = getUSCensusAgeDist() # Generate Random Ages with the same probability density distribution # as color matching experiment: sz_interval = 1 list_AgeRound = np.round(np.array(list_Age) / sz_interval) * sz_interval h = math.histogram(list_AgeRound, bins=np.unique(list_AgeRound), bin_center=True)[0] p = h / h.sum() # probability density distribution var_age = np.random.choice(np.unique(list_AgeRound), \ size = n_obs, replace = True,\ p = p) # Set requested wavelength range: if wl is not None: wl = getwlr(wl3=wl) else: wl = _WL LMS_All = np.nan * np.ones((3 + 1, wl.shape[0], n_obs)) for k in range(n_obs): t_LMS, t_trans_lens, t_trans_macula, t_sens_photopig = cie2006cmfsEx(age = var_age[k], fieldsize = fieldsize, wl = wl,\ var_od_lens = vAll['od_lens'][k], var_od_macula = vAll['od_macula'][k], \ var_od_L = vAll['od_L'][k], var_od_M = vAll['od_M'][k], var_od_S = vAll['od_S'][k],\ var_shft_L = vAll['shft_L'][k], var_shft_M = vAll['shft_M'][k], var_shft_S = vAll['shft_S'][k],\ out = 'LMS,trans_lens,trans_macula,sens_photopig') LMS_All[:, :, k] = t_LMS # listout = out.split(',') # if ('trans_lens' in listout) | ('trans_macula' in listout) | ('trans_photopig' in listout): # trans_lens[:,k] = t_trans_lens # trans_macula[:,k] = t_trans_macula # sens_photopig[:,:,k] = t_sens_photopig if n_obs == 1: LMS_All = np.squeeze(LMS_All, axis=2) if ('xyz' in out.lower().split(',')): LMS_All = lmsb_to_xyzb(LMS_All, fieldsize, out='xyz', allow_negative_values=allow_negative_values) out = out.replace('xyz', 'LMS').replace('XYZ', 'LMS') if ('lms' in out.lower().split(',')): out = out.replace('lms', 'LMS') if (out == 'LMS'): return LMS_All elif (out == 'LMS,var_age,vAll'): return LMS_All, var_age, vAll else: return eval(out)