code: def is_feasible(self, obs_df, risk=0.5):
          
          # todo deal with pi eqs
  
          is_feasible = pd.Series(data=True, index=obs_df.index)
          for lt_obs in self.pst.less_than_obs_constraints:
              if risk != 0.5:
                  val = self.get_risk_shifted_value(risk,obs_df.loc[lt_obs])
              else:
                  val = self.pst.observation_data.loc[lt_obs,"obsval"]
              is_feasible.loc[obs_df.loc[:,lt_obs]>=val] = False
          for gt_obs in self.pst.greater_than_obs_constraints:
              if risk != 0.5:
                  val = self.get_risk_shifted_value(risk,obs_df.loc[gt_obs])
              else:
                  val = self.pst.observation_data.loc[gt_obs,"obsval"]
              is_feasible.loc[obs_df.loc[:,gt_obs] <= val] = False
          return is_feasible
docs: identify which candidate solutions in obs_df (rows)
          are feasible with respect obs constraints (obs_df)
  
          Parameters
          ----------
          obs_df : pandas.DataFrame
              a dataframe with columns of obs names and rows of realizations
          risk : float
              risk value. If != 0.5, then risk shifting is used.  Otherwise, the
              obsval in Pst is used.  Default is 0.5.
  
  
          Returns
          -------
          is_feasible : pandas.Series
              series with obs_df.index and bool values