def val_changed(self, val_str):
        # Backup form state
        old_ma_unit, old_table = self._save_ma_unit_and_table_state(
                                table = self.two_by_two_table,
                                ma_unit = self.ma_unit, 
                                use_old_value=False)
        old_prevalence = self.current_prevalence
        
        new_text = self._get_txt_from_val_str(val_str)
        
        no_errors, display_scale_val = self._text_box_value_is_between_bounds(val_str, new_text)
        if no_errors is False: # There are errors
            self.restore_ma_unit_and_table(old_ma_unit,old_table, old_prevalence)
            calc_fncs.block_signals(self.entry_widgets, True)
            if val_str == "est":
                self.effect_txt_box.setFocus()
            elif val_str == "lower":
                self.low_txt_box.setFocus()
            elif val_str == "upper":
                self.high_txt_box.setFocus()
            elif val_str == "prevalence":
                self.prevalence_txt_box.setFocus()
            calc_fncs.block_signals(self.entry_widgets, False)
            return
        
        # If we got to this point it means everything is ok so far        
        try:
            if display_scale_val not in EMPTY_VALS:
                display_scale_val = float(display_scale_val)
            else:
                display_scale_val = None
        except ValueError:
            # a number wasn't entered; ignore
            # should probably clear out the box here, too.
            print "fail."
            return None
        

        calc_scale_val = meta_py_r.diagnostic_convert_scale(display_scale_val,
                                        self.cur_effect, convert_to="calc.scale")
        
        if val_str == "est":
            self.ma_unit.set_effect(self.cur_effect, self.group_str, calc_scale_val)
        elif val_str == "lower":
            self.ma_unit.set_lower(self.cur_effect, self.group_str, calc_scale_val)
        elif val_str == "upper":
            self.ma_unit.set_upper(self.cur_effect, self.group_str, calc_scale_val)
        elif val_str == "prevalence":
            pass

        new_ma_unit, new_table = self._save_ma_unit_and_table_state(
                table = self.two_by_two_table, ma_unit = self.ma_unit,
                use_old_value=False)
        new_prevalence = self._get_prevalence_str()
        restore_old_f = lambda: self.restore_ma_unit_and_table(old_ma_unit, old_table, old_prevalence)
        restore_new_f = lambda: self.restore_ma_unit_and_table(new_ma_unit, new_table, new_prevalence)
        command = calc_fncs.CommandFieldChanged(restore_new_f=restore_new_f, restore_old_f=restore_old_f, parent=self)
        self.undoStack.push(command)
        
        self.current_prevalence = new_prevalence
 def _update_data_table(self):
     '''Try to calculate rest of 2x2 table from existing cells'''
     
     calc_fncs.block_signals(self.entry_widgets, True)
     
     params = self._get_table_vals()
     computed_params = calc_fncs.compute_2x2_table(params)
     print "Computed Params", computed_params
     if computed_params:
         self._set_vals(computed_params) # computed --> table widget
     
     # Compute prevalence if possible
     if (not computed_params['c1sum'] in EMPTY_VALS) and (not computed_params['total'] in EMPTY_VALS):
         prevalence = float(computed_params['c1sum'])/float(computed_params['total'])
         prev_str = str(prevalence)[:7]
         self.prevalence_txt_box.setText("%s" % prev_str)
         self.enable_txt_box_input()
     
     calc_fncs.block_signals(self.entry_widgets, False)
    def clear_form(self):
        # For undo/redo
        old_ma_unit, old_tables_data = self._save_ma_unit_and_table_states(
                                tables = [self.simple_table,
                                          self.g1_pre_post_table,
                                          self.g2_pre_post_table],
                                ma_unit = self.ma_unit, 
                                use_old_value=False)
        old_correlation = self._get_correlation_str()
        
        self.metric_parameter = None  # } these two should go together
        self.enable_txt_box_input()   # }
        
        calc_fncs.block_signals(self.entry_widgets, True)
        # reset tables
        for table in self.tables:
            for row_index in range(len(self.cur_groups)):
                for var_index in range(table.columnCount()):
                    self._set_val(row_index, var_index, "", table=table)
        calc_fncs.block_signals(self.entry_widgets, False)
    
        self._copy_raw_data_from_table_to_ma_unit()

        # clear out effects stuff
        for metric in CONTINUOUS_ONE_ARM_METRICS + CONTINUOUS_TWO_ARM_METRICS:
            if ((self.cur_effect in CONTINUOUS_TWO_ARM_METRICS and metric in CONTINUOUS_TWO_ARM_METRICS) or
                (self.cur_effect in CONTINUOUS_ONE_ARM_METRICS and metric in CONTINUOUS_ONE_ARM_METRICS)):
                self.ma_unit.set_effect_and_ci(metric, self.group_str, None, None, None, mult=self.mult)
            else:
                # TODO: Do nothing for now..... treat the case where we have to switch group strings down the line
                pass
            
        # clear line edits
        self.set_current_effect()
        calc_fncs.block_signals(self.entry_widgets, True)
        self.correlation_pre_post.setText("0.0")
        calc_fncs.block_signals(self.entry_widgets, False)
        
        # For undo/redo
        self.enable_back_calculation_btn()
        new_ma_unit, new_tables_data = self._save_ma_unit_and_table_states(
                                            tables = [self.simple_table,
                                                      self.g1_pre_post_table,
                                                      self.g2_pre_post_table],
                                            ma_unit = self.ma_unit, 
                                            use_old_value=False)
        new_correlation = self._get_correlation_str()
        restore_old_f = lambda: self.restore_ma_unit_and_tables(old_ma_unit, old_tables_data, old_correlation)
        restore_new_f = lambda: self.restore_ma_unit_and_tables(new_ma_unit, new_tables_data, new_correlation)
        command = calc_fncs.CommandFieldChanged(restore_new_f=restore_new_f,
                                                restore_old_f=restore_old_f,
                                                parent=self)
        self.undoStack.push(command)
 def _text_box_value_is_between_bounds(self, val_str, new_text):
     display_scale_val = ""
     
     get_disp_scale_val_if_valid = partial(
             calc_fncs.evaluate, new_text=new_text, ma_unit=self.ma_unit,
             curr_effect=self.cur_effect, group_str=self.group_str,
             conv_to_disp_scale = partial(meta_py_r.diagnostic_convert_scale,
                                          metric_name=self.cur_effect,
                                          convert_to="display.scale"),
             parent=self, mult=self.mult)
     
     calc_fncs.block_signals(self.entry_widgets, True)
     try:
         if val_str == "est" and not is_empty(new_text):
             display_scale_val = get_disp_scale_val_if_valid(ci_param='est')
         elif val_str == "lower" and not is_empty(new_text):
             display_scale_val = get_disp_scale_val_if_valid(ci_param='low')
         elif val_str == "upper" and not is_empty(new_text):
             display_scale_val = get_disp_scale_val_if_valid(ci_param='high')
         elif val_str == "prevalence" and not is_empty(new_text):
             get_disp_scale_val_if_valid(opt_cmp_fn = lambda x: 0 <= float(x) <= 1,
                                         opt_cmp_msg="Prevalence must be between 0 and 1.")
     except:
         calc_fncs.block_signals(self.entry_widgets, False)
         return False, False
     calc_fncs.block_signals(self.entry_widgets, False)
     return True, display_scale_val
    def _text_box_value_is_between_bounds(self, val_str, new_text):
        display_scale_val = ""
        
        get_disp_scale_val_if_valid = partial(
                calc_fncs.evaluate, new_text=new_text, ma_unit=self.ma_unit,
                curr_effect=self.cur_effect, group_str=self.group_str,
                conv_to_disp_scale = partial(meta_py_r.continuous_convert_scale,
                                             metric_name=self.cur_effect,
                                             convert_to="display.scale"),
                                             parent=self, mult=self.mult)

        calc_fncs.block_signals(self.entry_widgets, True)
        try:
            if val_str == "est" and not _is_empty(new_text):
                display_scale_val = get_disp_scale_val_if_valid(ci_param='est')
            elif val_str == "lower" and not _is_empty(new_text):
                display_scale_val = get_disp_scale_val_if_valid(ci_param='low')
            elif val_str == "upper" and not _is_empty(new_text):
                display_scale_val = get_disp_scale_val_if_valid(ci_param='high')
            elif val_str == "correlation_pre_post" and not _is_empty(new_text):
                get_disp_scale_val_if_valid(opt_cmp_fn = lambda x: -1<=float(x)<=1,
                                            opt_cmp_msg="Correlation must be between -1 and +1")
        except:
            calc_fncs.block_signals(self.entry_widgets, False)
            return False, False
        calc_fncs.block_signals(self.entry_widgets, False)
        print("Val_str: %s" % val_str)
        return True,display_scale_val
 def _text_box_value_is_between_bounds(self, val_str, new_text):
     display_scale_val = ""
     
     get_disp_scale_val_if_valid = partial(
             calc_fncs.evaluate, new_text=new_text, ma_unit=self.ma_unit,
             curr_effect=self.cur_effect, group_str=self.group_str,
             conv_to_disp_scale = partial(meta_py_r.binary_convert_scale,
                                          metric_name=self.cur_effect,
                                          convert_to="display.scale"),
                                          parent=self,
                                          mult=self.mult)
     
     calc_fncs.block_signals(self.entry_widgets, True)
     try:
         if val_str == "est" and not is_empty(new_text):
             display_scale_val = get_disp_scale_val_if_valid(ci_param='est')
         elif val_str == "lower" and not is_empty(new_text):
             display_scale_val = get_disp_scale_val_if_valid(ci_param='low')
         elif val_str == "upper" and not is_empty(new_text):
             display_scale_val = get_disp_scale_val_if_valid(ci_param='high')
     except Exception:
         calc_fncs.block_signals(self.entry_widgets, False)
         return False,False
     calc_fncs.block_signals(self.entry_widgets, False)
     print("Val_str: %s" % val_str)
     return True,display_scale_val
    def _text_box_value_is_between_bounds(self, val_str, new_text):
        display_scale_val = ""

        get_disp_scale_val_if_valid = partial(
            calc_fncs.evaluate,
            new_text=new_text,
            ma_unit=self.ma_unit,
            curr_effect=self.cur_effect,
            group_str=self.group_str,
            conv_to_disp_scale=partial(meta_py_r.binary_convert_scale,
                                       metric_name=self.cur_effect,
                                       convert_to="display.scale"),
            parent=self,
            mult=self.mult)

        calc_fncs.block_signals(self.entry_widgets, True)
        try:
            if val_str == "est" and not is_empty(new_text):
                display_scale_val = get_disp_scale_val_if_valid(ci_param='est')
            elif val_str == "lower" and not is_empty(new_text):
                display_scale_val = get_disp_scale_val_if_valid(ci_param='low')
            elif val_str == "upper" and not is_empty(new_text):
                display_scale_val = get_disp_scale_val_if_valid(
                    ci_param='high')
        except Exception:
            calc_fncs.block_signals(self.entry_widgets, False)
            return False, False
        calc_fncs.block_signals(self.entry_widgets, False)
        print("Val_str: %s" % val_str)
        return True, display_scale_val
    def val_changed(self, val_str):
        # Backup form state
        old_ma_unit, old_tables_data = self._save_ma_unit_and_table_states(
                                tables = [self.simple_table,
                                          self.g1_pre_post_table,
                                          self.g2_pre_post_table],
                                ma_unit = self.ma_unit, 
                                use_old_value=False)
        old_correlation = self.current_correlation
        
        new_text = self._get_txt_from_val_str(val_str)
            
        
        no_errors, display_scale_val = self._text_box_value_is_between_bounds(val_str, new_text)
        if no_errors is False:
            print("There was an error while in val_changed")
            self.restore_ma_unit_and_tables(old_ma_unit,old_tables_data, old_correlation)
            calc_fncs.block_signals(self.entry_widgets, True)
            if val_str == "est":
                self.effect_txt_box.setFocus()
            elif val_str == "lower":
                self.low_txt_box.setFocus()
            elif val_str == "upper":
                self.high_txt_box.setFocus()
            elif val_str == "correlation_pre_post":
                self.correlation_pre_post.setFocus()
            calc_fncs.block_signals(self.entry_widgets, False)
            return
        
        # If we got to this point it means everything is ok so far
        try:
            if display_scale_val not in meta_globals.EMPTY_VALS:
                display_scale_val = float(display_scale_val)
            else:
                display_scale_val = None
        except ValueError:
            # a number wasn't entered; ignore
            # should probably clear out the box here, too.
            print "fail."
            return None
        
        calc_scale_val = meta_py_r.continuous_convert_scale(display_scale_val,
                                        self.cur_effect, convert_to="calc.scale")
                      
        if val_str == "est":
            self.ma_unit.set_effect(self.cur_effect, self.group_str, calc_scale_val)
        elif val_str == "lower":
            self.ma_unit.set_lower(self.cur_effect, self.group_str, calc_scale_val)
        elif val_str == "upper":
            self.ma_unit.set_upper(self.cur_effect, self.group_str, calc_scale_val)
        elif val_str == "correlation_pre_post":
            print "ok -- correlation set to %s" % self.correlation_pre_post.text()
            # Recompute the estimates
            self.impute_pre_post_data(self.g1_pre_post_table, 0)
            self.impute_pre_post_data(self.g2_pre_post_table, 1)
        
        self.impute_data() #### experimental
        

        new_ma_unit, new_tables_data = self._save_ma_unit_and_table_states(
                        tables = [self.simple_table,
                                  self.g1_pre_post_table,
                                  self.g2_pre_post_table],
                        ma_unit = self.ma_unit, 
                        use_old_value=False)
        new_correlation = self._get_correlation_str()
        restore_old_f = lambda: self.restore_ma_unit_and_tables(old_ma_unit, old_tables_data, old_correlation)
        restore_new_f = lambda: self.restore_ma_unit_and_tables(new_ma_unit, new_tables_data, new_correlation)
        command = calc_fncs.CommandFieldChanged(restore_new_f=restore_new_f,
                                                restore_old_f=restore_old_f,
                                                parent=self)
        self.undoStack.push(command)
        
        self.current_correlation = new_correlation
    def val_changed(self, val_str):
        # Backup form state
        old_ma_unit, old_tables_data = self._save_ma_unit_and_table_states(
            tables=[
                self.simple_table, self.g1_pre_post_table,
                self.g2_pre_post_table
            ],
            ma_unit=self.ma_unit,
            use_old_value=False)
        old_correlation = self.current_correlation

        new_text = self._get_txt_from_val_str(val_str)

        no_errors, display_scale_val = self._text_box_value_is_between_bounds(
            val_str, new_text)
        if no_errors is False:
            print("There was an error while in val_changed")
            self.restore_ma_unit_and_tables(old_ma_unit, old_tables_data,
                                            old_correlation)
            calc_fncs.block_signals(self.entry_widgets, True)
            if val_str == "est":
                self.effect_txt_box.setFocus()
            elif val_str == "lower":
                self.low_txt_box.setFocus()
            elif val_str == "upper":
                self.high_txt_box.setFocus()
            elif val_str == "correlation_pre_post":
                self.correlation_pre_post.setFocus()
            calc_fncs.block_signals(self.entry_widgets, False)
            return

        # If we got to this point it means everything is ok so far
        try:
            if display_scale_val not in EMPTY_VALS:
                display_scale_val = float(display_scale_val)
            else:
                display_scale_val = None
        except ValueError:
            # a number wasn't entered; ignore
            # should probably clear out the box here, too.
            print "fail."
            return None

        calc_scale_val = meta_py_r.continuous_convert_scale(
            display_scale_val, self.cur_effect, convert_to="calc.scale")

        if val_str == "est":
            self.ma_unit.set_effect(self.cur_effect, self.group_str,
                                    calc_scale_val)
        elif val_str == "lower":
            self.ma_unit.set_lower(self.cur_effect, self.group_str,
                                   calc_scale_val)
        elif val_str == "upper":
            self.ma_unit.set_upper(self.cur_effect, self.group_str,
                                   calc_scale_val)
        elif val_str == "correlation_pre_post":
            print "ok -- correlation set to %s" % self.correlation_pre_post.text(
            )
            # Recompute the estimates
            self.impute_pre_post_data(self.g1_pre_post_table, 0)
            self.impute_pre_post_data(self.g2_pre_post_table, 1)

        self.impute_data()  #### experimental

        new_ma_unit, new_tables_data = self._save_ma_unit_and_table_states(
            tables=[
                self.simple_table, self.g1_pre_post_table,
                self.g2_pre_post_table
            ],
            ma_unit=self.ma_unit,
            use_old_value=False)
        new_correlation = self._get_correlation_str()
        restore_old_f = lambda: self.restore_ma_unit_and_tables(
            old_ma_unit, old_tables_data, old_correlation)
        restore_new_f = lambda: self.restore_ma_unit_and_tables(
            new_ma_unit, new_tables_data, new_correlation)
        command = calc_fncs.CommandFieldChanged(restore_new_f=restore_new_f,
                                                restore_old_f=restore_old_f,
                                                parent=self)
        self.undoStack.push(command)

        self.current_correlation = new_correlation
    def clear_form(self):
        # For undo/redo
        old_ma_unit, old_tables_data = self._save_ma_unit_and_table_states(
            tables=[
                self.simple_table, self.g1_pre_post_table,
                self.g2_pre_post_table
            ],
            ma_unit=self.ma_unit,
            use_old_value=False)
        old_correlation = self._get_correlation_str()

        self.metric_parameter = None  # } these two should go together
        self.enable_txt_box_input()  # }

        calc_fncs.block_signals(self.entry_widgets, True)
        # reset tables
        for table in self.tables:
            for row_index in range(len(self.cur_groups)):
                for var_index in range(table.columnCount()):
                    self._set_val(row_index, var_index, "", table=table)
        calc_fncs.block_signals(self.entry_widgets, False)

        self._copy_raw_data_from_table_to_ma_unit()

        # clear out effects stuff
        for metric in CONTINUOUS_ONE_ARM_METRICS + CONTINUOUS_TWO_ARM_METRICS:
            if ((self.cur_effect in CONTINUOUS_TWO_ARM_METRICS
                 and metric in CONTINUOUS_TWO_ARM_METRICS)
                    or (self.cur_effect in CONTINUOUS_ONE_ARM_METRICS
                        and metric in CONTINUOUS_ONE_ARM_METRICS)):
                self.ma_unit.set_effect_and_ci(metric,
                                               self.group_str,
                                               None,
                                               None,
                                               None,
                                               mult=self.mult)
            else:
                # TODO: Do nothing for now..... treat the case where we have to switch group strings down the line
                pass

        # clear line edits
        self.set_current_effect()
        calc_fncs.block_signals(self.entry_widgets, True)
        self.correlation_pre_post.setText("0.0")
        calc_fncs.block_signals(self.entry_widgets, False)

        # For undo/redo
        self.enable_back_calculation_btn()
        new_ma_unit, new_tables_data = self._save_ma_unit_and_table_states(
            tables=[
                self.simple_table, self.g1_pre_post_table,
                self.g2_pre_post_table
            ],
            ma_unit=self.ma_unit,
            use_old_value=False)
        new_correlation = self._get_correlation_str()
        restore_old_f = lambda: self.restore_ma_unit_and_tables(
            old_ma_unit, old_tables_data, old_correlation)
        restore_new_f = lambda: self.restore_ma_unit_and_tables(
            new_ma_unit, new_tables_data, new_correlation)
        command = calc_fncs.CommandFieldChanged(restore_new_f=restore_new_f,
                                                restore_old_f=restore_old_f,
                                                parent=self)
        self.undoStack.push(command)