def execute_binFeatures(self,analysis_id_I,features_I=[],n_bins_I=[]):
        '''bin features of continuous data
        INPUT:
        analysis_id_I = string,
        features_I = [] of string, e.g. ['mutation_position','mutation_frequency']
        n_bins_I = int, the number of bins per feature (if bins is empty, bins will be calculated)

        OUTPUT:
        '''
        data_O = [];
        calculatehistogram = calculate_histogram();
        #get the analysis information
        experiment_ids,sample_names = [],[];
        experiment_ids,sample_names = self.get_experimentIDAndSampleName_analysisID_dataStage01ResequencingAnalysis(analysis_id_I);
        #bin each feature
        for features_cnt,features in enumerate(features_I):
            n_bins = 50;
            calc_bins_I = True;
            if n_bins_I and n_bins_I[features_cnt]:
                n_bins = n_bins_I[features_cnt];
                calc_bins_I = False;
            if features == 'mutation_position':
                data_hist = [];
                #get all the data for the analysis
                for sn_cnt,sn in enumerate(sample_names):
                    data_tmp = [];
                    data_tmp = self.get_AllMutationPositions_experimentIDAndSampleName_dataStage01ResequencingMutationsAnnotated(experiment_ids[sn_cnt],sn);
                    if data_tmp:
                        data_hist.extend(data_tmp);
                #make the bins for the histogram
                x_O,dx_O,y_O = calculatehistogram.histogram(data_I=data_hist,n_bins_I=n_bins,calc_bins_I=calc_bins_I);
                tmp = self.record_histogram(analysis_id_I,features,'',x_O,dx_O,y_O);
                data_O.extend(tmp);
                    
            elif features == 'mutation_frequency':
                data_hist = [];
                #get all the data for the analysis
                for sn_cnt,sn in enumerate(sample_names):
                    data_tmp = [];
                    data_tmp = self.get_AllMutationFrequencies_experimentIDAndSampleName_dataStage01ResequencingMutationsAnnotated(experiment_ids[sn_cnt],sn);
                    if data_tmp:
                        data_hist.extend(data_tmp);
                #make the bins for the histogram
                x_O,dx_O,y_O = calculatehistogram.histogram(data_I=data_hist,n_bins_I=n_bins,calc_bins_I=calc_bins_I);
                tmp = self.record_histogram(analysis_id_I,features,'',x_O,dx_O,y_O);
                data_O.extend(tmp);
            else:
                print('feature not recongnized');
        #add the data to the database
        self.add_dataStage01ResequencingHistogram(data_O);
    def export_dataStage02PhysiologySampledPoints_js(self,
        analysis_id_I,
        simulation_ids_I = [],
        rxn_ids_I = [],
        query_I={},
        data_dir_I='tmp'
        ):
        '''Visualize the sampling distribution
        DESCRIPTION:
        tile1=filtermenu
        tile2=sampling distribution
        tile3=table
        '''
        calculatehistogram = calculate_histogram();
        physiology_analysis_query = stage02_physiology_analysis_query(self.session,self.engine,self.settings);
        data_sampledPoints_O = [];
        data_O = [];
        #get the analysis info
        simulation_ids = physiology_analysis_query.get_simulationID_analysisID_dataStage02PhysiologyAnalysis(analysis_id_I);
        if simulation_ids_I:
            simulation_ids = [s for s in simulation_ids if s in simulation_ids_I];
        for simulation_id in simulation_ids:
            #get the data_dirs for the simulations and read in the points
            sampledPoints = self.get_rows_simulationID_dataStage02PhysiologySampledPoints(simulation_id);
            sampledPoints = sampledPoints[0];
            data_sampledPoints_O.append(sampledPoints);
            # get simulation information
            simulation_info_all = [];
            simulation_info_all = self.get_rows_simulationIDAndSimulationType_dataStage02PhysiologySimulation(simulation_id,'sampling');
            if not simulation_info_all:
                print('simulation not found!')
                return;
            simulation_info = simulation_info_all[0]; # unique constraint guarantees only 1 row will be returned
            # get simulation parameters
            simulation_parameters_all = [];
            simulation_parameters_all = self.get_rows_simulationID_dataStage02PhysiologySamplingParameters(simulation_id);
            if not simulation_parameters_all:
                print('simulation not found!')
                return;
            simulation_parameters = simulation_parameters_all[0]; # unique constraint guarantees only 1 row will be returned
            #fill the sampledData with the actual points
            sampling = cobra_sampling(model_I=None,data_dir_I = sampledPoints['data_dir'],loops_I=sampledPoints['infeasible_loops']);
            if simulation_parameters['sampler_id']=='gpSampler':
                # load the results of sampling
                sampling.get_points_matlab(matlab_data=None,sampler_model_name='sampler_out');
                sampling.remove_loopsFromPoints();
            elif simulation_parameters['sampler_id']=='optGpSampler':
                sampling.get_points_json();
                sampling.remove_loopsFromPoints();
            else:
                print('sampler_id not recognized');
            #store the sampledPoints
            for k,v in sampling.points.items():
                if rxn_ids_I: 
                    if not k in rxn_ids_I: 
                        continue;
                n_bins = 100;
                calc_bins_I = False;
                x_O,dx_O,y_O = calculatehistogram.histogram(data_I=v,n_bins_I=n_bins,calc_bins_I=calc_bins_I);
                for i,b in enumerate(x_O):
                    tmp = {
                        'simulation_id':simulation_id,
                        'rxn_id':k,
                        #'feature_units':feature_units,
                        'bin':b,
                        'bin_width':dx_O[i],
                        'frequency':int(y_O[i]),
                        'used_':True,
                        'comment_':None};
                    data_O.append(tmp);
            #data_listDict = listDict();
            #data_listDict.set_dictList(sampling.points);
            #data_listDict.convert_dictList2DataFrame();
            #points, rxn_ids = data_listDict.get_flattenedDataAndColumnLabels();
            #data_listDict.clear_allData();
            #data_listDict.add_column2DataFrame('rxn_id',rxn_ids);
            #data_listDict.add_column2DataFrame('points',points);
            #data_listDict.add_column2DataFrame('simulation_id',simulation_id);
            #data_listDict.convert_dataFrame2ListDict();
            #data_O.extend(data_listDict.get_listDict());
        #make the DDT histograms  
        # visualization parameters
        data1_keys = ['simulation_id',
                      'rxn_id',
                      'bin',
                      ];
        data1_nestkeys = [
            'bin'
            ];
        data1_keymap = {
                'xdata':'bin',
                'ydata':'frequency',
                'serieslabel':'simulation_id',
                'featureslabel':'bin',
                'tooltiplabel':'rxn_id',
                'ydatalb':None,
                'ydataub':None};
        
        
        nsvgtable = ddt_container_filterMenuAndChart2dAndTable();
        nsvgtable.make_filterMenuAndChart2dAndTable(
            data_filtermenu=data_O,
            data_filtermenu_keys=data1_keys,
            data_filtermenu_nestkeys=data1_nestkeys,
            data_filtermenu_keymap=data1_keymap,
            data_svg_keys=None,
            data_svg_nestkeys=None,
            data_svg_keymap=None,
            data_table_keys=None,
            data_table_nestkeys=None,
            data_table_keymap=None,
            data_svg=None,
            data_table=None,
            svgtype='verticalbarschart2d_01',
            tabletype='responsivetable_01',
            svgx1axislabel='',
            svgy1axislabel='',
            tablekeymap = [data1_keymap],
            svgkeymap = [data1_keymap],
            formtile2datamap=[0],
            tabletile2datamap=[0],
            svgtile2datamap=[0], #calculated on the fly
            svgfilters=None,
            svgtileheader='Sampled points',
            tablefilters=None,
            tableheaders=None
            );

        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = nsvgtable.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(nsvgtable.get_allObjects());