diff --git a/docs/API/foam/additional_constraints.html b/docs/API/foam/additional_constraints.html index a833fa5..4d5ac6b 100644 --- a/docs/API/foam/additional_constraints.html +++ b/docs/API/foam/additional_constraints.html @@ -236,158 +236,159 @@

97 ) 98 indices_to_drop = dataframe_theory.apply(func, axis=1) 99 for index_to_drop in indices_to_drop: -100 if (index_to_drop is not None) and (index_to_drop == index_to_drop): -101 dataframe_theory.drop(index_to_drop, inplace=True) -102 -103 output_file = f"{nsigma}sigmaBox_{merit_values_file}" -104 Path(output_file).parent.mkdir(parents=True, exist_ok=True) -105 dataframe_theory.to_hdf(f"{output_file}", "surface_constrained_models", format="table", mode="w") -106 +100 # Check if index_to_drop equals itself to filter out NaN values +101 if (index_to_drop is not None) and (index_to_drop == index_to_drop): +102 dataframe_theory.drop(index_to_drop, inplace=True) +103 +104 output_file = f"{nsigma}sigmaBox_{merit_values_file}" +105 Path(output_file).parent.mkdir(parents=True, exist_ok=True) +106 dataframe_theory.to_hdf(f"{output_file}", "surface_constrained_models", format="table", mode="w") 107 -108################################################################################ -109def get_age( -110 model, df, free_parameters=["Z", "M", "logD", "aov", "fov", "Xc"], evolution_parameter="Xc", evolution_step=-1e-2 -111): -112 """ -113 Get the age of the models one step older and younger than the provided model. -114 -115 Parameters -116 ---------- -117 model: pandas series -118 Parameters of the model. -119 df: pandas dataFrame -120 Dataframe with the model parameters and age (and surface info) of the theoretical models. -121 free_parameters: list of strings -122 List of all the parameters varied in the model grid. -123 evolution_parameter: string -124 Name of the parameter that is used to track the evolutionary steps of the model. -125 evolution_step: float -126 Change in the evolutionary parameter from one step to the next (negative if quantity decreases, e.g. central hydrogen content Xc) -127 -128 Returns -129 ---------- -130 min_age, max_age: tuple of integers -131 Age of the model one step younger and older than the provided model, -132 these are the minimum and maximum age to accept models in the isochrone-cloud. -133 """ -134 -135 # copy to prevent deletion in the list outside this function -136 params = list(free_parameters) -137 params.remove(evolution_parameter) -138 for param in params: -139 df = df.loc[np.isclose(getattr(df, param), getattr(model, param))] -140 -141 model_evolution_attr = getattr(model, evolution_parameter) -142 grid_evolution_attr = getattr(df, evolution_parameter) -143 -144 if abs(model_evolution_attr - max(grid_evolution_attr)) < abs(0.5 * evolution_step): -145 min_age = 0 -146 max_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr + evolution_step)].age).iloc[0]) -147 elif abs(model_evolution_attr - min(grid_evolution_attr)) < abs(0.5 * evolution_step): -148 min_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr - evolution_step)].age).iloc[0]) -149 age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr)].age).iloc[0]) -150 max_age = age + age - min_age -151 else: -152 min_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr - evolution_step)].age).iloc[0]) -153 max_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr + evolution_step)].age).iloc[0]) -154 return min_age, max_age -155 +108 +109################################################################################ +110def get_age( +111 model, df, free_parameters=["Z", "M", "logD", "aov", "fov", "Xc"], evolution_parameter="Xc", evolution_step=-1e-2 +112): +113 """ +114 Get the age of the models one step older and younger than the provided model. +115 +116 Parameters +117 ---------- +118 model: pandas series +119 Parameters of the model. +120 df: pandas dataFrame +121 Dataframe with the model parameters and age (and surface info) of the theoretical models. +122 free_parameters: list of strings +123 List of all the parameters varied in the model grid. +124 evolution_parameter: string +125 Name of the parameter that is used to track the evolutionary steps of the model. +126 evolution_step: float +127 Change in the evolutionary parameter from one step to the next (negative if quantity decreases, e.g. central hydrogen content Xc) +128 +129 Returns +130 ---------- +131 min_age, max_age: tuple of integers +132 Age of the model one step younger and older than the provided model, +133 these are the minimum and maximum age to accept models in the isochrone-cloud. +134 """ +135 +136 # copy to prevent deletion in the list outside this function +137 params = list(free_parameters) +138 params.remove(evolution_parameter) +139 for param in params: +140 df = df.loc[np.isclose(getattr(df, param), getattr(model, param))] +141 +142 model_evolution_attr = getattr(model, evolution_parameter) +143 grid_evolution_attr = getattr(df, evolution_parameter) +144 +145 if abs(model_evolution_attr - max(grid_evolution_attr)) < abs(0.5 * evolution_step): +146 min_age = 0 +147 max_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr + evolution_step)].age).iloc[0]) +148 elif abs(model_evolution_attr - min(grid_evolution_attr)) < abs(0.5 * evolution_step): +149 min_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr - evolution_step)].age).iloc[0]) +150 age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr)].age).iloc[0]) +151 max_age = age + age - min_age +152 else: +153 min_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr - evolution_step)].age).iloc[0]) +154 max_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr + evolution_step)].age).iloc[0]) +155 return min_age, max_age 156 -157################################################################################ -158def enforce_binary_constraints( -159 df_theory_row, -160 constraint_companion=None, -161 isocloud_grid_summary=None, -162 nsigma=3, -163 surface_grid_dataframe=None, -164 free_parameters=["Z", "M", "logD", "aov", "fov", "Xc"], -165 evolution_parameter="Xc", -166 evolution_step=-1e-2, -167): -168 """ -169 Enforce an n-sigma constraint on the models based on -170 spectroscopic observations of the binary companion employing isochrone-clouds. -171 Assumes the same metallicity 'Z' for both primary and secondary, -172 masses 'M' compatible with observed mass ratio 'q', and ages similar within 1 gridstep. -173 -174 Parameters -175 ---------- -176 df_theory_row: tuple, made of (int, pandas series) -177 tuple returned from pandas.iterrows(), first tuple entry is the row index of the pandas dataFrame -178 second tuple entry is a pandas series, containing a row from the pandas dataFrame. -179 (This row holds model parameters, the merit function value, and surface properties.) -180 constraint_companion: dict -181 Information on the companion star, including surface parameters, mass ratio (q), the errors, -182 and a boolean indicating whether the primary or secondary star is assumed pulsating and hence being modelled. -183 isocloud_grid_summary: dict -184 Nested dictionary, the keys at its two levels are metallicity and mass. -185 Holds the surface properties of the grid for the isochrone-cloud modelling per combination of metallicity-mass. -186 nsigma: int -187 How many sigma you want to make the interval to accept models. -188 surface_grid_dataframe: pandas DataFrame -189 DataFrame with the surface properties and ages of the model-grid. -190 free_parameters: list of strings -191 List of all the parameters varied in the model grid. -192 evolution_parameter: string -193 Name of the parameter that is used to track the evolutionary steps of the model. -194 evolution_step: float -195 Change in the evolutionary parameter from one step to the next (negative if quantity decreases, e.g. central hydrogen content Xc) -196 -197 Returns -198 ---------- -199 index: int or None -200 Index of the dataframe that needs to be removed if binary constraints do not allow the model to remain. -201 Returns None if the binary constraints do not discard the model. -202 """ -203 model = df_theory_row -204 min_age, max_age = get_age( -205 model, -206 surface_grid_dataframe, -207 free_parameters=free_parameters, -208 evolution_parameter=evolution_parameter, -209 evolution_step=evolution_step, -210 ) -211 q = constraint_companion["q"] -212 q_err = constraint_companion["q_err"] -213 if constraint_companion["primary_pulsates"]: -214 m2_min = round(model.M * (q - q_err), 1) -215 m2_max = round(model.M * (q + q_err), 1) -216 else: -217 m2_min = round(model.M / (q + q_err), 1) -218 m2_max = round(model.M / (q - q_err), 1) -219 -220 isocloud_dict = isocloud_grid_summary[f"{model.Z}"] -221 for key_mass, df in zip(isocloud_dict.keys(), isocloud_dict.values()): -222 # Convert from string to float for the comparisons -223 key_mass = float(key_mass) -224 if key_mass < m2_min or key_mass > m2_max: -225 # Only keep models that fall within mass range -226 continue -227 else: -228 df = df[(df.star_age < max_age) & (df.star_age > min_age)] -229 -230 if df.shape[0] == 0: -231 continue -232 -233 # Check for all provided constraints if the track passes through the uncertainty region -234 if constraint_companion["Teff"] is not None: -235 df = df[ -236 df.log_Teff < np.log10(constraint_companion["Teff"] + nsigma * constraint_companion["Teff_err"]) -237 ] -238 df = df[ -239 df.log_Teff > np.log10(constraint_companion["Teff"] - nsigma * constraint_companion["Teff_err"]) -240 ] -241 if constraint_companion["logg"] is not None: -242 df = df[df.log_g < constraint_companion["logg"] + nsigma * constraint_companion["logg_err"]] -243 df = df[df.log_g > constraint_companion["logg"] - nsigma * constraint_companion["logg_err"]] -244 if constraint_companion["logL"] is not None: -245 df = df[df.log_L < constraint_companion["logL"] + nsigma * constraint_companion["logL_err"]] -246 df = df[df.log_L > constraint_companion["logL"] - nsigma * constraint_companion["logL_err"]] -247 if df.shape[0] > 0: -248 # If some models fall within the constraints, return None to not remove the model. -249 return None -250 -251 return model.name +157 +158################################################################################ +159def enforce_binary_constraints( +160 df_theory_row, +161 constraint_companion=None, +162 isocloud_grid_summary=None, +163 nsigma=3, +164 surface_grid_dataframe=None, +165 free_parameters=["Z", "M", "logD", "aov", "fov", "Xc"], +166 evolution_parameter="Xc", +167 evolution_step=-1e-2, +168): +169 """ +170 Enforce an n-sigma constraint on the models based on +171 spectroscopic observations of the binary companion employing isochrone-clouds. +172 Assumes the same metallicity 'Z' for both primary and secondary, +173 masses 'M' compatible with observed mass ratio 'q', and ages similar within 1 grid step. +174 +175 Parameters +176 ---------- +177 df_theory_row: tuple, made of (int, pandas series) +178 tuple returned from pandas.iterrows(), first tuple entry is the row index of the pandas dataFrame +179 second tuple entry is a pandas series, containing a row from the pandas dataFrame. +180 (This row holds model parameters, the merit function value, and surface properties.) +181 constraint_companion: dict +182 Information on the companion star, including surface parameters, mass ratio (q), the errors, +183 and a boolean indicating whether the primary or secondary star is assumed pulsating and hence being modelled. +184 isocloud_grid_summary: dict +185 Nested dictionary, the keys at its two levels are metallicity and mass. +186 Holds the surface properties of the grid for the isochrone-cloud modelling per combination of metallicity-mass. +187 nsigma: int +188 How many sigma you want to make the interval to accept models. +189 surface_grid_dataframe: pandas DataFrame +190 DataFrame with the surface properties and ages of the model-grid. +191 free_parameters: list of strings +192 List of all the parameters varied in the model grid. +193 evolution_parameter: string +194 Name of the parameter that is used to track the evolutionary steps of the model. +195 evolution_step: float +196 Change in the evolutionary parameter from one step to the next (negative if quantity decreases, e.g. central hydrogen content Xc) +197 +198 Returns +199 ---------- +200 index: int or None +201 Index of the dataframe that needs to be removed if binary constraints do not allow the model to remain. +202 Returns None if the binary constraints do not discard the model. +203 """ +204 model = df_theory_row +205 min_age, max_age = get_age( +206 model, +207 surface_grid_dataframe, +208 free_parameters=free_parameters, +209 evolution_parameter=evolution_parameter, +210 evolution_step=evolution_step, +211 ) +212 q = constraint_companion["q"] +213 q_err = constraint_companion["q_err"] +214 if constraint_companion["primary_pulsates"]: +215 m2_min = round(model.M * (q - q_err), 1) +216 m2_max = round(model.M * (q + q_err), 1) +217 else: +218 m2_min = round(model.M / (q + q_err), 1) +219 m2_max = round(model.M / (q - q_err), 1) +220 +221 isocloud_dict = isocloud_grid_summary[f"{model.Z}"] +222 for key_mass, df in zip(isocloud_dict.keys(), isocloud_dict.values()): +223 # Convert from string to float for the comparisons +224 key_mass = float(key_mass) +225 if key_mass < m2_min or key_mass > m2_max: +226 # Only keep models that fall within mass range +227 continue +228 else: +229 df = df[(df.star_age < max_age) & (df.star_age > min_age)] +230 +231 if df.shape[0] == 0: +232 continue +233 +234 # Check for all provided constraints if the track passes through the uncertainty region +235 if constraint_companion["Teff"] is not None: +236 df = df[ +237 df.log_Teff < np.log10(constraint_companion["Teff"] + nsigma * constraint_companion["Teff_err"]) +238 ] +239 df = df[ +240 df.log_Teff > np.log10(constraint_companion["Teff"] - nsigma * constraint_companion["Teff_err"]) +241 ] +242 if constraint_companion["logg"] is not None: +243 df = df[df.log_g < constraint_companion["logg"] + nsigma * constraint_companion["logg_err"]] +244 df = df[df.log_g > constraint_companion["logg"] - nsigma * constraint_companion["logg_err"]] +245 if constraint_companion["logL"] is not None: +246 df = df[df.log_L < constraint_companion["logL"] + nsigma * constraint_companion["logL_err"]] +247 df = df[df.log_L > constraint_companion["logL"] - nsigma * constraint_companion["logL_err"]] +248 if df.shape[0] > 0: +249 # If some models fall within the constraints, return None to not remove the model. +250 return None +251 +252 return model.name @@ -488,12 +489,13 @@

98 ) 99 indices_to_drop = dataframe_theory.apply(func, axis=1) 100 for index_to_drop in indices_to_drop: -101 if (index_to_drop is not None) and (index_to_drop == index_to_drop): -102 dataframe_theory.drop(index_to_drop, inplace=True) -103 -104 output_file = f"{nsigma}sigmaBox_{merit_values_file}" -105 Path(output_file).parent.mkdir(parents=True, exist_ok=True) -106 dataframe_theory.to_hdf(f"{output_file}", "surface_constrained_models", format="table", mode="w") +101 # Check if index_to_drop equals itself to filter out NaN values +102 if (index_to_drop is not None) and (index_to_drop == index_to_drop): +103 dataframe_theory.drop(index_to_drop, inplace=True) +104 +105 output_file = f"{nsigma}sigmaBox_{merit_values_file}" +106 Path(output_file).parent.mkdir(parents=True, exist_ok=True) +107 dataframe_theory.to_hdf(f"{output_file}", "surface_constrained_models", format="table", mode="w") @@ -540,52 +542,52 @@

Parameters
-
110def get_age(
-111    model, df, free_parameters=["Z", "M", "logD", "aov", "fov", "Xc"], evolution_parameter="Xc", evolution_step=-1e-2
-112):
-113    """
-114    Get the age of the models one step older and younger than the provided model.
-115
-116    Parameters
-117    ----------
-118    model: pandas series
-119        Parameters of the model.
-120    df: pandas dataFrame
-121        Dataframe with the model parameters and age (and surface info) of the theoretical models.
-122    free_parameters: list of strings
-123        List of all the parameters varied in the model grid.
-124    evolution_parameter: string
-125        Name of the parameter that is used to track the evolutionary steps of the model.
-126    evolution_step: float
-127        Change in the evolutionary parameter from one step to the next (negative if quantity decreases, e.g. central hydrogen content Xc)
-128
-129    Returns
-130    ----------
-131    min_age, max_age: tuple of integers
-132        Age of the model one step younger and older than the provided model,
-133        these are the minimum and maximum age to accept models in the isochrone-cloud.
-134    """
-135
-136    # copy to prevent deletion in the list outside this function
-137    params = list(free_parameters)
-138    params.remove(evolution_parameter)
-139    for param in params:
-140        df = df.loc[np.isclose(getattr(df, param), getattr(model, param))]
-141
-142    model_evolution_attr = getattr(model, evolution_parameter)
-143    grid_evolution_attr = getattr(df, evolution_parameter)
-144
-145    if abs(model_evolution_attr - max(grid_evolution_attr)) < abs(0.5 * evolution_step):
-146        min_age = 0
-147        max_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr + evolution_step)].age).iloc[0])
-148    elif abs(model_evolution_attr - min(grid_evolution_attr)) < abs(0.5 * evolution_step):
-149        min_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr - evolution_step)].age).iloc[0])
-150        age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr)].age).iloc[0])
-151        max_age = age + age - min_age
-152    else:
-153        min_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr - evolution_step)].age).iloc[0])
-154        max_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr + evolution_step)].age).iloc[0])
-155    return min_age, max_age
+            
111def get_age(
+112    model, df, free_parameters=["Z", "M", "logD", "aov", "fov", "Xc"], evolution_parameter="Xc", evolution_step=-1e-2
+113):
+114    """
+115    Get the age of the models one step older and younger than the provided model.
+116
+117    Parameters
+118    ----------
+119    model: pandas series
+120        Parameters of the model.
+121    df: pandas dataFrame
+122        Dataframe with the model parameters and age (and surface info) of the theoretical models.
+123    free_parameters: list of strings
+124        List of all the parameters varied in the model grid.
+125    evolution_parameter: string
+126        Name of the parameter that is used to track the evolutionary steps of the model.
+127    evolution_step: float
+128        Change in the evolutionary parameter from one step to the next (negative if quantity decreases, e.g. central hydrogen content Xc)
+129
+130    Returns
+131    ----------
+132    min_age, max_age: tuple of integers
+133        Age of the model one step younger and older than the provided model,
+134        these are the minimum and maximum age to accept models in the isochrone-cloud.
+135    """
+136
+137    # copy to prevent deletion in the list outside this function
+138    params = list(free_parameters)
+139    params.remove(evolution_parameter)
+140    for param in params:
+141        df = df.loc[np.isclose(getattr(df, param), getattr(model, param))]
+142
+143    model_evolution_attr = getattr(model, evolution_parameter)
+144    grid_evolution_attr = getattr(df, evolution_parameter)
+145
+146    if abs(model_evolution_attr - max(grid_evolution_attr)) < abs(0.5 * evolution_step):
+147        min_age = 0
+148        max_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr + evolution_step)].age).iloc[0])
+149    elif abs(model_evolution_attr - min(grid_evolution_attr)) < abs(0.5 * evolution_step):
+150        min_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr - evolution_step)].age).iloc[0])
+151        age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr)].age).iloc[0])
+152        max_age = age + age - min_age
+153    else:
+154        min_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr - evolution_step)].age).iloc[0])
+155        max_age = int((df.loc[np.isclose(grid_evolution_attr, model_evolution_attr + evolution_step)].age).iloc[0])
+156    return min_age, max_age
 
@@ -628,107 +630,107 @@
Returns
-
159def enforce_binary_constraints(
-160    df_theory_row,
-161    constraint_companion=None,
-162    isocloud_grid_summary=None,
-163    nsigma=3,
-164    surface_grid_dataframe=None,
-165    free_parameters=["Z", "M", "logD", "aov", "fov", "Xc"],
-166    evolution_parameter="Xc",
-167    evolution_step=-1e-2,
-168):
-169    """
-170    Enforce an n-sigma constraint on the models based on
-171    spectroscopic observations of the binary companion employing isochrone-clouds.
-172    Assumes the same metallicity 'Z' for both primary and secondary,
-173    masses 'M' compatible with observed mass ratio 'q', and ages similar within 1 gridstep.
-174
-175    Parameters
-176    ----------
-177    df_theory_row: tuple, made of (int, pandas series)
-178        tuple returned from pandas.iterrows(), first tuple entry is the row index of the pandas dataFrame
-179        second tuple entry is a pandas series, containing a row from the pandas dataFrame.
-180        (This row holds model parameters, the merit function value, and surface properties.)
-181    constraint_companion: dict
-182        Information on the companion star, including surface parameters, mass ratio (q), the errors,
-183        and a boolean indicating whether the primary or secondary star is assumed pulsating and hence being modelled.
-184    isocloud_grid_summary: dict
-185        Nested dictionary, the keys at its two levels are metallicity and mass.
-186        Holds the surface properties of the grid for the isochrone-cloud modelling per combination of metallicity-mass.
-187    nsigma: int
-188        How many sigma you want to make the interval to accept models.
-189    surface_grid_dataframe: pandas DataFrame
-190        DataFrame with the surface properties and ages of the model-grid.
-191    free_parameters: list of strings
-192        List of all the parameters varied in the model grid.
-193    evolution_parameter: string
-194        Name of the parameter that is used to track the evolutionary steps of the model.
-195    evolution_step: float
-196        Change in the evolutionary parameter from one step to the next (negative if quantity decreases, e.g. central hydrogen content Xc)
-197
-198    Returns
-199    ----------
-200    index: int or None
-201        Index of the dataframe that needs to be removed if binary constraints do not allow the model to remain.
-202        Returns None if the binary constraints do not discard the model.
-203    """
-204    model = df_theory_row
-205    min_age, max_age = get_age(
-206        model,
-207        surface_grid_dataframe,
-208        free_parameters=free_parameters,
-209        evolution_parameter=evolution_parameter,
-210        evolution_step=evolution_step,
-211    )
-212    q = constraint_companion["q"]
-213    q_err = constraint_companion["q_err"]
-214    if constraint_companion["primary_pulsates"]:
-215        m2_min = round(model.M * (q - q_err), 1)
-216        m2_max = round(model.M * (q + q_err), 1)
-217    else:
-218        m2_min = round(model.M / (q + q_err), 1)
-219        m2_max = round(model.M / (q - q_err), 1)
-220
-221    isocloud_dict = isocloud_grid_summary[f"{model.Z}"]
-222    for key_mass, df in zip(isocloud_dict.keys(), isocloud_dict.values()):
-223        # Convert from string to float for the comparisons
-224        key_mass = float(key_mass)
-225        if key_mass < m2_min or key_mass > m2_max:
-226            # Only keep models that fall within mass range
-227            continue
-228        else:
-229            df = df[(df.star_age < max_age) & (df.star_age > min_age)]
-230
-231            if df.shape[0] == 0:
-232                continue
-233
-234            # Check for all provided constraints if the track passes through the uncertainty region
-235            if constraint_companion["Teff"] is not None:
-236                df = df[
-237                    df.log_Teff < np.log10(constraint_companion["Teff"] + nsigma * constraint_companion["Teff_err"])
-238                ]
-239                df = df[
-240                    df.log_Teff > np.log10(constraint_companion["Teff"] - nsigma * constraint_companion["Teff_err"])
-241                ]
-242            if constraint_companion["logg"] is not None:
-243                df = df[df.log_g < constraint_companion["logg"] + nsigma * constraint_companion["logg_err"]]
-244                df = df[df.log_g > constraint_companion["logg"] - nsigma * constraint_companion["logg_err"]]
-245            if constraint_companion["logL"] is not None:
-246                df = df[df.log_L < constraint_companion["logL"] + nsigma * constraint_companion["logL_err"]]
-247                df = df[df.log_L > constraint_companion["logL"] - nsigma * constraint_companion["logL_err"]]
-248            if df.shape[0] > 0:
-249                # If some models fall within the constraints, return None to not remove the model.
-250                return None
-251
-252    return model.name
+            
160def enforce_binary_constraints(
+161    df_theory_row,
+162    constraint_companion=None,
+163    isocloud_grid_summary=None,
+164    nsigma=3,
+165    surface_grid_dataframe=None,
+166    free_parameters=["Z", "M", "logD", "aov", "fov", "Xc"],
+167    evolution_parameter="Xc",
+168    evolution_step=-1e-2,
+169):
+170    """
+171    Enforce an n-sigma constraint on the models based on
+172    spectroscopic observations of the binary companion employing isochrone-clouds.
+173    Assumes the same metallicity 'Z' for both primary and secondary,
+174    masses 'M' compatible with observed mass ratio 'q', and ages similar within 1 grid step.
+175
+176    Parameters
+177    ----------
+178    df_theory_row: tuple, made of (int, pandas series)
+179        tuple returned from pandas.iterrows(), first tuple entry is the row index of the pandas dataFrame
+180        second tuple entry is a pandas series, containing a row from the pandas dataFrame.
+181        (This row holds model parameters, the merit function value, and surface properties.)
+182    constraint_companion: dict
+183        Information on the companion star, including surface parameters, mass ratio (q), the errors,
+184        and a boolean indicating whether the primary or secondary star is assumed pulsating and hence being modelled.
+185    isocloud_grid_summary: dict
+186        Nested dictionary, the keys at its two levels are metallicity and mass.
+187        Holds the surface properties of the grid for the isochrone-cloud modelling per combination of metallicity-mass.
+188    nsigma: int
+189        How many sigma you want to make the interval to accept models.
+190    surface_grid_dataframe: pandas DataFrame
+191        DataFrame with the surface properties and ages of the model-grid.
+192    free_parameters: list of strings
+193        List of all the parameters varied in the model grid.
+194    evolution_parameter: string
+195        Name of the parameter that is used to track the evolutionary steps of the model.
+196    evolution_step: float
+197        Change in the evolutionary parameter from one step to the next (negative if quantity decreases, e.g. central hydrogen content Xc)
+198
+199    Returns
+200    ----------
+201    index: int or None
+202        Index of the dataframe that needs to be removed if binary constraints do not allow the model to remain.
+203        Returns None if the binary constraints do not discard the model.
+204    """
+205    model = df_theory_row
+206    min_age, max_age = get_age(
+207        model,
+208        surface_grid_dataframe,
+209        free_parameters=free_parameters,
+210        evolution_parameter=evolution_parameter,
+211        evolution_step=evolution_step,
+212    )
+213    q = constraint_companion["q"]
+214    q_err = constraint_companion["q_err"]
+215    if constraint_companion["primary_pulsates"]:
+216        m2_min = round(model.M * (q - q_err), 1)
+217        m2_max = round(model.M * (q + q_err), 1)
+218    else:
+219        m2_min = round(model.M / (q + q_err), 1)
+220        m2_max = round(model.M / (q - q_err), 1)
+221
+222    isocloud_dict = isocloud_grid_summary[f"{model.Z}"]
+223    for key_mass, df in zip(isocloud_dict.keys(), isocloud_dict.values()):
+224        # Convert from string to float for the comparisons
+225        key_mass = float(key_mass)
+226        if key_mass < m2_min or key_mass > m2_max:
+227            # Only keep models that fall within mass range
+228            continue
+229        else:
+230            df = df[(df.star_age < max_age) & (df.star_age > min_age)]
+231
+232            if df.shape[0] == 0:
+233                continue
+234
+235            # Check for all provided constraints if the track passes through the uncertainty region
+236            if constraint_companion["Teff"] is not None:
+237                df = df[
+238                    df.log_Teff < np.log10(constraint_companion["Teff"] + nsigma * constraint_companion["Teff_err"])
+239                ]
+240                df = df[
+241                    df.log_Teff > np.log10(constraint_companion["Teff"] - nsigma * constraint_companion["Teff_err"])
+242                ]
+243            if constraint_companion["logg"] is not None:
+244                df = df[df.log_g < constraint_companion["logg"] + nsigma * constraint_companion["logg_err"]]
+245                df = df[df.log_g > constraint_companion["logg"] - nsigma * constraint_companion["logg_err"]]
+246            if constraint_companion["logL"] is not None:
+247                df = df[df.log_L < constraint_companion["logL"] + nsigma * constraint_companion["logL_err"]]
+248                df = df[df.log_L > constraint_companion["logL"] - nsigma * constraint_companion["logL_err"]]
+249            if df.shape[0] > 0:
+250                # If some models fall within the constraints, return None to not remove the model.
+251                return None
+252
+253    return model.name
 

Enforce an n-sigma constraint on the models based on spectroscopic observations of the binary companion employing isochrone-clouds. Assumes the same metallicity 'Z' for both primary and secondary, -masses 'M' compatible with observed mass ratio 'q', and ages similar within 1 gridstep.

+masses 'M' compatible with observed mass ratio 'q', and ages similar within 1 grid step.

Parameters