def export_dataStage02PhysiologyPairWiseTestMetabolites_js(self,analysis_id_I,data_dir_I='tmp'):
     '''Export data for a volcano plot
     Visuals:
     1. volcano plot
     2. sample vs. sample (FC)
     3. sample vs. sample (concentration)
     4. sample vs. sample (p-value)'''
     
     #get the data for the analysis
     data_O = [];
     data_O = self.get_rows_analysisID_dataStage02PhysiologyPairWiseTestMetabolites(analysis_id_I);
     # make the data parameters
     data1_keys = ['analysis_id','simulation_id_1','simulation_id_2',
                   'met_id','flux_units','test_description'
                 ];
     data1_nestkeys = ['analysis_id'];
     data1_keymap = {'ydata':'pvalue_negLog10',
                     'xdata':'fold_change',
                     'serieslabel':'',
                     'featureslabel':'met_id'};
     # make the data object
     dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
     # make the tile parameter objects
     formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
     formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
     formtileparameters_O.update(formparameters_O);
     svgparameters_O = {"svgtype":'volcanoplot2d_01',
                        "svgkeymap":[data1_keymap],
                         'svgid':'svg1',
                         "svgmargin":{ 'top': 50, 'right': 50, 'bottom': 50, 'left': 50 },
                         "svgwidth":500,
                         "svgheight":350,
                         "svgx1axislabel":'Fold Change [geometric]',
                         "svgy1axislabel":'Probability [-log10(P)]'};
     svgtileparameters_O = {'tileheader':'Volcano plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
     svgtileparameters_O.update(svgparameters_O);
     tableparameters_O = {"tabletype":'responsivetable_01',
                 'tableid':'table1',
                 "tableclass":"table  table-condensed table-hover",
                 "tablefilters":None,
 			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
     tabletileparameters_O = {'tileheader':'pairWiseTest','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     tabletileparameters_O.update(tableparameters_O);
     parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
     tile2datamap_O = {"filtermenu1":[0],"tile2":[0],"tile3":[0]};
     # dump the data to a json file
     filtermenuobject_O = None;
     ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
     if data_dir_I=='tmp':
         filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
     elif data_dir_I=='data_json':
         data_json_O = ddtutilities.get_allObjects_js();
         return data_json_O;
     with open(filename_str,'w') as file:
         file.write(ddtutilities.get_allObjects());
 def export_dataStage01RNASequencingGenesFpkmTracking_js(self,analysis_id_I,data_dir_I='tmp'):
     '''Export data for a box and whiskers plot'''
     # get the analysis information
     experiment_ids,sample_names = [],[];
     experiment_ids,sample_names = self.get_experimentIDAndSampleName_analysisID_dataStage01RNASequencingAnalysis(analysis_id_I);
     data_O = [];
     for sample_name_cnt,sample_name in enumerate(sample_names):
         # query fpkm data:
         fpkms = [];
         fpkms = self.get_rows_experimentIDAndSampleName_dataStage01RNASequencingGenesFpkmTracking(experiment_ids[sample_name_cnt],sample_name);
         data_O.extend(fpkms);
     # dump chart parameters to a js files
     data1_keys = ['experiment_id','sample_name','gene_short_name'
                 ];
     data1_nestkeys = ['gene_short_name'];
     data1_keymap = {'xdata':'gene_short_name',
                     'ydatamean':'FPKM',
                     'ydatalb':'FPKM_conf_lo',
                     'ydataub':'FPKM_conf_hi',
                     'serieslabel':'sample_name',
                     'featureslabel':'gene_short_name'};
     # make the data object
     dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
     # make the tile parameter objects
     formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
     formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
     formtileparameters_O.update(formparameters_O);
     svgparameters_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data1_keymap],
                         'svgid':'svg1',
                         "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                         "svgwidth":500,"svgheight":350,
                         "svgx1axislabel":"gene","svgy1axislabel":"FPKM",
 						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
     svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
     svgtileparameters_O.update(svgparameters_O);
     tableparameters_O = {"tabletype":'responsivetable_01',
                 'tableid':'table1',
                 "tablefilters":None,
                 "tableclass":"table  table-condensed table-hover",
 			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
     tabletileparameters_O = {'tileheader':'FPKM','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     tabletileparameters_O.update(tableparameters_O);
     parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
     tile2datamap_O = {"filtermenu1":[0],"tile2":[0],"tile3":[0]};
     # dump the data to a json file
     ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
         return data_json_O;
     with open(filename_str,'w') as file:
         file.write(ddtutilities.get_allObjects());
    def export_thermodynamicAnalysisEscher_js(self,analysis_id_I,simulation_id_I=None,
                     measured_concentration_coverage_criteria_I=0.49,
                     measured_dG_f_coverage_criteria_I=0.99,
                     data_dir_I = 'tmp'):
        
        data_O = [];
        # Get the simulation information
        if simulation_id_I:
            simulation_id = simulation_id_I;
        else:
            simulation_ids = [];
            simulation_ids = self.get_simulationID_analysisID_dataStage03QuantificationAnalysis(analysis_id_I);
        if not simulation_ids:
            print('No simulation found for the analysis_id ' + analysis_id_I);
        elif len(simulation_ids)>1:
            print('More than 1 simulation found for the analysis_id ' + analysis_id_I);
            simulation_id_I = simulation_ids[0];
        else:
            simulation_id_I = simulation_ids[0];
        # get the simulation info
        simulation = [];
        simulation = self.get_rows_simulationID_dataStage03QuantificationSimulation(simulation_id_I);
        for row in simulation:
            model_id = row['model_id'];
            # get the time-points
            tp = row['time_point'];
            # get the sample name abbreviations
            sna = row['sample_name_abbreviation'];
            # get the experiment
            experiment_id = row['experiment_id'];
            # get metabolomicsData
            concentrations = [];
            concentrations = self.get_rows_experimentIDAndTimePointAndSampleNameAbbreviations_dataStage03QuantificationMetabolomicsData(experiment_id,tp,sna);
            # get dGr
            dG_r = [];
            dG_r = self.get_rows_experimentIDAndModelIDAndTimePointAndSampleNameAbbreviations_dataStage03QuantificationDGr(experiment_id,model_id,tp,sna,measured_concentration_coverage_criteria_I,measured_dG_f_coverage_criteria_I);       
            if dG_r:
                for cnt,d in enumerate(dG_r):
                    dG_r[cnt]['dG_r_mean'] = numpy.mean([d['dG_r_lb'],d['dG_r_ub']]);
        # Get the map information
        map = [];
        map = self.get_rows_modelID_modelsEschermaps('iJO1366');

        # Make the ddt objects
        data1_keys = ['experiment_id',
                      #'model_id',
                      'time_point','sample_name_abbreviation','dG_r','dG_r_units'
                    ];
        data1_nestkeys = ['sample_name_abbreviation'];
        data1_keymap = {'values':'dG_r_mean','key':'rxn_id'};
        data2_keys = ['experiment_id','time_point',
                      'sample_name_abbreviation','met_id',
                      'concentration_units'
                    ];
        data2_nestkeys = ['sample_name_abbreviation'];
        data2_keymap = {'values':'concentration','key':'met_id'};
        data3_keys = ['model_id','eschermap_id'
                    ];
        data3_nestkeys = ['model_id'];
        data3_keymap = {'data':'eschermap_json'};
        # make the data object
        dataobject_O = [{"data":dG_r,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":concentrations,"datakeys":data2_keys,"datanestkeys":data2_nestkeys},
                        {"data":map,"datakeys":data3_keys,"datanestkeys":data3_nestkeys}];
        # make the tile parameter objects
        # form 1
        formtileparameters1_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters1_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters1_O.update(formparameters1_O);
        # form 2
        formtileparameters2_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu2",'rowid':"row1",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters2_O = {'htmlid':'filtermenuform2',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit2','text':'submit'},"formresetbuttonidtext":{'id':'reset2','text':'reset'},"formupdatebuttonidtext":{'id':'update2','text':'update'}};
        formtileparameters2_O.update(formparameters2_O);
        # form 3
        formtileparameters3_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu3",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters3_O = {'htmlid':'filtermenuform3',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit3','text':'submit'},"formresetbuttonidtext":{'id':'reset3','text':'reset'},"formupdatebuttonidtext":{'id':'update3','text':'update'}};
        formtileparameters3_O.update(formparameters3_O);
        # form 3
        # escher
        htmlparameters_O = {"htmlkeymap":[data1_keymap,data2_keymap],
                        'htmltype':'escher_01','htmlid':'html1',
                        'escherdataindex':{"reactiondata":0,"metabolitedata":1,"mapdata":2},
                        'escherembeddedcss':None,
                        'escheroptions':None};
        htmltileparameters_O = {'tileheader':'Escher map','tiletype':'html','tileid':"tile1",'rowid':"row3",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        htmltileparameters_O.update(htmlparameters_O);
        # table 1
        tableparameters1_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters1_O = {'tileheader':'dG_r','tiletype':'table','tileid':"table1",'rowid':"row4",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters1_O.update(tableparameters1_O);
        # table 2
        tableparameters2_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters2_O = {'tileheader':'Concentrations','tiletype':'table','tileid':"table2",'rowid':"row5",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters2_O.update(tableparameters2_O);
        # output objects
        parametersobject_O = [formtileparameters1_O,formtileparameters2_O,formtileparameters3_O,htmltileparameters_O,tabletileparameters1_O,tabletileparameters2_O];
        tile2datamap_O = {"filtermenu1":[0],"filtermenu2":[1],"filtermenu3":[2],"tile1":[0,1,2],"table1":[0],"table2":[1]};
        filtermenuobject_O = [{"filtermenuid":"filtermenu1","filtermenuhtmlid":"filtermenuform1",
                "filtermenusubmitbuttonid":"submit1","filtermenuresetbuttonid":"reset1",
                "filtermenuupdatebuttonid":"update1"},{"filtermenuid":"filtermenu2","filtermenuhtmlid":"filtermenuform2",
                "filtermenusubmitbuttonid":"submit2","filtermenuresetbuttonid":"reset2",
                "filtermenuupdatebuttonid":"update2"},{"filtermenuid":"filtermenu3","filtermenuhtmlid":"filtermenuform3",
                "filtermenusubmitbuttonid":"submit3","filtermenuresetbuttonid":"reset3",
                "filtermenuupdatebuttonid":"update3"}];
        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_thermodynamicAnalysis_js(self,analysis_id_I,simulation_ids_I=[],
                     measured_concentration_coverage_criteria_I=0.49,
                     measured_dG_f_coverage_criteria_I=0.99,
                     bullet_chart_I = True,
                     data_dir_I = 'tmp'):
        '''Export the results of the thermodynamic analysis to js'''
        concentrations_O = [];
        dG_r_O = [];
        tcc_O = [];
        # Get the simulation information
        if simulation_ids_I:
            simulation_ids = simulation_ids_I;
        else:
            simulation_ids = [];
            simulation_ids = self.get_simulationID_analysisID_dataStage03QuantificationAnalysis(analysis_id_I);
        for simulation_id in simulation_ids:
            # get the simulation info
            simulation = [];
            simulation = self.get_rows_simulationID_dataStage03QuantificationSimulation(simulation_id);
            for row in simulation:
                model_id = row['model_id'];
                # get the time-points
                tp = row['time_point'];
                # get the sample name abbreviations
                sna = row['sample_name_abbreviation'];
                # get the experiment
                experiment_id = row['experiment_id'];
                ## get metabolomicsData
                #concentrations = [];
                #concentrations = self.get_rows_experimentIDAndTimePointAndSampleNameAbbreviations_dataStage03QuantificationMetabolomicsData(experiment_id_I,tp,sna);
                ## extend the data
                #concentrations_O.extend(concentrations);
                ## get dGr
                #dG_r = [];
                #dG_r = self.get_rows_experimentIDAndModelIDAndTimePointAndSampleNameAbbreviations_dataStage03QuantificationDGr(experiment_id_I,model_id,tp,sna,measured_concentration_coverage_criteria_I,measured_dG_f_coverage_criteria_I);       
                ## extend the data
                #dG_r_O.extend(dG_r);
                # get the tcc data
                tcc = [];
                tcc = self.get_rows_experimentIDAndModelIDAndTimePointAndSampleNameAbbreviations_dataStage03QuantificationTCC(experiment_id,model_id,tp,sna,measured_concentration_coverage_criteria_I,measured_dG_f_coverage_criteria_I);
                # record data
                if tcc: 
                    for cnt,d in enumerate(tcc):
                        tcc[cnt]['dG_r_mean'] = numpy.mean([d['dG_r_lb'],d['dG_r_ub']]);
                    tcc_O.extend(tcc);

        # dump chart parameters to a js files
        data1_keys = ['experiment_id',
                      'model_id',
                      'time_point','sample_name_abbreviation','rxn_id','dG_r_units','feasible'
                    ];
        data1_nestkeys = ['rxn_id'];
        if bullet_chart_I:
            data1_keymap = {'xdata':'rxn_id',
                        'ydatamean':'dG_r_mean',
                        'ydatalb':'dG_r_lb',
                        'ydataub':'dG_r_ub',
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'rxn_id'};
        else: # not implemented
            data1_keymap = {'xdata':'rxn_id',
                        'ydatamean':'dG_r_mean',
                        'ydatalb':'dG_r_lb',
                        'ydataub':'dG_r_ub',
                        'ydatamin':'min',
                        'ydatamax':'max',
                        'ydataiq1':'dG_r_lb_stdev',
                        'ydataiq3':'dG_r_ub_stdev',
                        'ydatamedian':'dG_r',
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'rxn_id'};
        # make the data object
        dataobject_O = [{"data":tcc_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        svgparameters_O = {"svgtype":'boxandwhiskersplot2d_01',"svgkeymap":[data1_keymap,data1_keymap],
                            'svgid':'svg1',
                            "svgmargin":{ 'top': 50, 'right': 350, 'bottom': 50, 'left': 50 },
                            "svgwidth":750,"svgheight":350,
                            "svgx1axislabel":"rxn_id","svgy1axislabel":"dG_r",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_O = {'tileheader':'dG_r','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        svgtileparameters_O.update(svgparameters_O);
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'dG_r','tiletype':'table','tileid':"tile3",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
        tile2datamap_O = {"filtermenu1":[0],"tile2":[0],"tile3":[0]};
        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_visualizationPipeline_js(self,pipeline_id_I,data_dir_I="tmp"):
        """export visualization_pipeline for visualization"""

        print("exporting visualization_pipeline...")

        # query the pipeline info
        data1_pipeline = {};
        data1_pipeline = self.get_pipeline_pipelineID_visualizationPipeline(pipeline_id_I);
        data1_O = [];
        data1_O = self.get_rows_pipelineID_visualizationPipeline(pipeline_id_I);
        # query the pipeline description
        data2_O = [];
        data2_O = self.get_rows_pipelineID_visualizationPipelineDescription(pipeline_id_I);
        # query user privileges (new table?)
        data1_query_O=[];
        #data1_query_O.g
        # data parameters
        data1_keys = ['table_name','data_export_id','pipeline_id'#,'container_export_id'
                      ];
        data1_nestkeys = ['data_export_id'];
        data1_keymap = {'buttonparameter':'data_export_id','liparameter':'table_name',
                        'buttontext':'data_export_id','litext':'table_name'};
        data2_keys = ['pipeline_id','pipeline_section','pipeline_heading','pipeline_tileorder'
                      ];
        data2_nestkeys = ['pipeline_id'];
        data2_keymap = {'htmlmediasrc':'pipeline_media','htmlmediaalt':'',
                        'htmlmediahref':'pipeline_href','htmlmediaheading':'pipeline_heading',
                        'htmlmediaparagraph':'pipeline_paragraph'};
        # make the data, parameters, and tile2datamap variables:
        dataobject_O = [];
        parametersobject_O = [];
        tile2datamap_O = {};
        tile_cnt = 0;
        # pipeline_description:
        if data2_O:
            for i,d in enumerate(data2_O):
                tileid = "tile" + str(tile_cnt);
                colid = "col" + str(i);
                tileheader = d['pipeline_section'];
                htmlid = "html" + str(tile_cnt);
                tileparameters = {'tileheader':tileheader,'tiletype':'html','tileid':tileid,'rowid':"row1",'colid':colid,
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
                htmlparameters={"htmlkeymap":[data2_keymap],
                            'htmltype':'media_01','htmlid':htmlid};
                tileparameters.update(htmlparameters);
                parametersobject_O.append(tileparameters);
                dataobject_O.append({"data":[d],"datakeys":data2_keys,"datanestkeys":data2_nestkeys});
                tile2datamap_O.update({tileid:[tile_cnt]});
                tile_cnt+=1;
        # pipeline:
        if data1_pipeline:
            data1_dict = {};
            for data_export_id in data1_pipeline['data_export_id']:
                if data_export_id is not None:
                    data1_dict[data_export_id]=[];
            for d in data1_O:
                if d['data_export_id'] is not None:
                    data1_dict[d['data_export_id']].append(d);
            data1_keys = list(data1_dict.keys());
            data1_keys.sort();
            col_cnt = 0;
            #for k,v in data1_dict.iteritems():
            for k in data1_keys:
                tileid = "tile" + str(tile_cnt);
                colid = "col" + str(col_cnt);
                tileheader = data1_dict[k][0]['pipeline_id'];
                htmlid = "html" + str(tile_cnt);
                #tileparameters = {'tileheader':tileheader,'tiletype':'html','tileid':tileid,'rowid':"row2",'colid':colid,
                #    'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
                #hrefparameters = {"hrefurl":'pipeline.html',"htmlkeymap":[data1_keymap],
                #                'htmltype':'href_01','htmlid':htmlid};
                tileparameters = {
                    'tileheader':tileheader,
                    'tiletype':'html',
                    'tileid':tileid,
                    'rowid':"row2",
                    'colid':colid,
                    'tileclass':"panel panel-default",
                    'rowclass':"row",
                    'colclass':"col-sm-6",
                    "formsubmitbuttonidtext":{'id':'submit1','text':'submit'}};
                hrefparameters = {
                    "hrefurl":'pipeline.html',
                    "htmlkeymap":[data1_keymap],
                    'htmltype':'href_02',
                    'htmlid':htmlid};
                tileparameters.update(hrefparameters);
                parametersobject_O.append(tileparameters);
                dataobject_O.append({"data":data1_dict[k],"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
                tile2datamap_O.update({tileid:[tile_cnt]});
                tile_cnt+=1;
                col_cnt+=1;
                
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01MQResultsTable_metricPlot_js(self,experiment_id_I,sample_names_I=[],component_names_I=[],measurement_I='calculated_concentration',data_dir_I="tmp"):
        ''' export a metric plot
        INPUT:
        experiment_id_I = experiment_id
        sample_names_I = sample_names
        component_names_I = component names
        measurement_I = measurement to plot, supports calculated_concentration, height_ratio, area_ratio, height, area, rt'''

        # get the data:
        data_O = [];
        cnt = 0;
        #Query unique sample_name/component_name for the analysis
        # get sample names
        if sample_names_I:
            sample_names = sample_names_I;
        else:
            sample_names = [];
            sample_types = ['Quality Control','Unknown','Standard','Blank'];
            for st in sample_types:
                sample_names_tmp = [];
                sample_names_tmp = self.get_sampleNames_experimentIDAndSampleType(experiment_id_I,st);
                sample_names.extend(sample_names_tmp);
        # create database table
        for sn in sample_names:
            # get component names
            if component_names_I:
                component_names = component_names_I;
            else:
                component_names = [];
                component_names = self.get_componentsNames_experimentIDAndSampleName(experiment_id_I,sn);
            for cn in component_names:
                # get the row
                rows = {};
                rows = self.get_row_sampleNameAndComponentName(sn,cn);
                if rows:
                    rows['acquisition_date_and_time'] = self.convert_datetime2string(rows['acquisition_date_and_time'])
                    rows['index_'] = cnt;
                    rows['experiment_id']=experiment_id_I;
                    data_O.append(rows);
                    cnt+=1;
        # get the sample_names_I    
        # dump chart parameters to a js files
        data1_keys = [
                    'experiment_id',
                    'sample_name',
                    'component_name',
                    measurement_I,
                    'acquisition_date_and_time',
                    'sample_type',
                    ];
        data1_nestkeys = ['component_name'];
        data1_keymap = {'xdata':'index_',
                        'ydata':measurement_I,
                        'serieslabel':'component_name',
                        'featureslabel':'sample_name'};
        parameters = {"chart1margin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                    "chart1width":500,"chart1height":350,
                  "chart1title":"Metric Plot", "chart1x1axislabel":"sample_name","chart1y1axislabel":"measurement"}
        # make the data object
        dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        formparameters_O = {'htmlid':'filtermenuform1','htmltype':'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        svgparameters_O = {"svgtype":'scatterlineplot2d_01',"svgkeymap":[data1_keymap,data1_keymap],
                            'svgid':'svg1',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":500,"svgheight":350,
                            "svgx1axislabel":"sample_name","svgy1axislabel":"measurement_value",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_O = {'tileheader':'Metric Plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
        svgtileparameters_O.update(svgparameters_O);
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'Metric plot','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
        tile2datamap_O = {"filtermenu1":[0],"tile2":[0,1],"tile3":[0]};
        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01NormalizedAndAverages_js(self,
                analysis_id_I,
                sample_name_abbreviations_I=[],
                sample_names_I=[],
                component_names_I=[],
                cv_threshold_I=40,
                extracellular_threshold_I=80,
                data_dir_I='tmp'):
        '''export data_stage01_quantification_normalized and averages for visualization with ddt'''

        calc = calculate_interface();
        
        print('export_dataStage01Normalized_js...')
        data_norm_broth = [];
        data_norm_filtrate = [];
        data_norm_combined = [];
        data_ave = [];

        #SPLIT 1:
        #1 query unique calculated_concentration_units/sample_name_abbreviations/component_names/component_group_names/time_points/sample_names/sample_ids/sample_description
        uniqueRows_all = self.getQueryResult_groupNormalizedAveragesSamples_analysisID_dataStage01QuantificationNormalizedAndAverages(
                analysis_id_I
            );
        #2 filter in broth samples
        uniqueRows = self.filter_groupNormalizedAveragesSamples_experimentID_dataStage01QuantificationNormalizedAndAverages_limsSampleAndSampleID(
                uniqueRows_all,
                calculated_concentration_units_I=[],
                component_names_I=component_names_I,
                component_group_names_I=[],
                sample_names_I=sample_names_I,
                sample_name_abbreviations_I=sample_name_abbreviations_I,
                time_points_I=[],
            );
        if type(uniqueRows)==type(listDict()):
            uniqueRows.convert_dataFrame2ListDict()
            uniqueRows = uniqueRows.get_listDict();
        replicates_tmp = {};#reorganize the data into a dictionary for quick traversal of the replicates
        for uniqueRow_cnt,uniqueRow in enumerate(uniqueRows):
            unique = (
                      uniqueRow['sample_name_abbreviation'],
                      uniqueRow['experiment_id'],
                      uniqueRow['time_point'],
                      uniqueRow['component_name'],
                      uniqueRow['calculated_concentration_units'])
            if not unique in replicates_tmp.keys():
                replicates_tmp[unique] = [];
            replicates_tmp[unique].append(uniqueRow);
        for unique,replicates in replicates_tmp.items():
            #get data from averages once per sample_name_abbreviation/component_name
            #print('exporting sample_name_abbreviation ' + replicates[0]['sample_name_abbreviation'] + " and component_name " + replicates[0]['component_name']);
            # get the averages and %CV samples
            row_ave = {};
            row_ave = self.get_row_experimentIDAndSampleNameAbbreviationAndTimePointAndComponentNameAndCalculatedConcentrationCVAndExtracellularPercent_dataStage01Averages(
                    replicates[0]['experiment_id'],
                    replicates[0]['sample_name_abbreviation'],
                    replicates[0]['time_point'],
                    replicates[0]['component_name'],
                    cv_threshold_I=cv_threshold_I,
                    extracellular_threshold_I=extracellular_threshold_I);
            if row_ave:
                stdev = calc.convert_cv2StDev(row_ave['calculated_concentration_filtrate_average'],row_ave['calculated_concentration_filtrate_cv']);
                row_ave['calculated_concentration_filtrate_lb'] = row_ave['calculated_concentration_filtrate_average']-stdev;
                row_ave['calculated_concentration_filtrate_ub'] = row_ave['calculated_concentration_filtrate_average']+stdev;
                stdev = calc.convert_cv2StDev(row_ave['calculated_concentration_broth_average'],row_ave['calculated_concentration_broth_cv']);
                row_ave['calculated_concentration_broth_lb'] = row_ave['calculated_concentration_broth_average']-stdev;
                row_ave['calculated_concentration_broth_ub'] = row_ave['calculated_concentration_broth_average']+stdev;
                stdev = calc.convert_cv2StDev(row_ave['calculated_concentration_average'],row_ave['calculated_concentration_cv']);
                row_ave['calculated_concentration_lb'] = row_ave['calculated_concentration_average']-stdev;
                row_ave['calculated_concentration_ub'] = row_ave['calculated_concentration_average']+stdev;
                row_ave['analysis_id'] = analysis_id_I;

                # get data from normalized
                filtrate_conc = [];
                broth_conc = [];
                for rep in replicates:
                    row = {};
                    row['analysis_id'] = analysis_id_I;
                    row['extracellular_percent'] = row_ave['extracellular_percent']
                    row['calculated_concentration_cv'] = row_ave['calculated_concentration_cv']
                    row.update(rep)
                    if rep['sample_desc'] == 'Filtrate':
                        data_norm_filtrate.append(row);
                        filtrate_conc.append(rep['calculated_concentration'])
                    if rep['sample_desc'] == 'Broth':
                        data_norm_broth.append(row);
                        broth_conc.append(rep['calculated_concentration'])
                    data_norm_combined.append(row);

                #add data to aggregate and sample_name_abbreviations_all
                if not broth_conc: broth_conc = [0];
                if not filtrate_conc: filtrate_conc = [0];
                row_ave['calculated_concentration_min']=min(broth_conc+filtrate_conc)
                row_ave['calculated_concentration_max']=max(broth_conc+filtrate_conc)
                row_ave['calculated_concentration_broth_min']=min(broth_conc)
                row_ave['calculated_concentration_broth_max']=max(broth_conc)
                row_ave['calculated_concentration_filtrate_min']=min(filtrate_conc)
                row_ave['calculated_concentration_filtrate_max']=max(filtrate_conc)
                data_ave.append(row_ave);

        # dump chart parameters to a js files
        data1_keys = ['analysis_id',
                      'experiment_id',
                      'sample_name',
                      'sample_id',
                      'sample_name_abbreviation',
                      'component_group_name',
                      'component_name',
                      'calculated_concentration_units',
                      'extracellular_percent',
                      'calculated_concentration_cv'
                    ];
        data1_nestkeys = ['component_name'];
        data1_keymap = {'xdata':'component_name',
                        'ydata':'calculated_concentration',
                        #'ydatalb':'peakInfo_lb',
                        #'ydataub':'peakInfo_ub',
                        #'ydatamin':None,
                        #'ydatamax':None,
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'sample_name'};
        data2_keys = ['analysis_id',
                      'experiment_id',
                      'sample_name_abbreviation',
                      'time_point',
                      'component_group_name',
                      'component_name',
                      'calculated_concentration_units',
                      'extracellular_percent',
                      'calculated_concentration_broth_cv'
                    ];
        data2_nestkeys = ['component_name'];
        data2_keymap = {'xdata':'component_name',
                        'ydatamean':'calculated_concentration_broth_average',
                        'ydatalb':'calculated_concentration_broth_lb',
                        'ydataub':'calculated_concentration_broth_ub',
                        'ydatamin':'calculated_concentration_broth_min',
                        'ydatamax':'calculated_concentration_broth_max',
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'component_name'};
        data3_keys = ['analysis_id',
                      'experiment_id',
                      'sample_name_abbreviation',
                      'time_point',
                      'component_group_name',
                      'component_name',
                      'calculated_concentration_units',
                      'extracellular_percent',
                      'calculated_concentration_filtrate_cv',
                    ];
        data3_nestkeys = ['component_name'];
        data3_keymap = {'xdata':'component_name',
                        'ydatamean':'calculated_concentration_filtrate_average',
                        'ydatalb':'calculated_concentration_filtrate_lb',
                        'ydataub':'calculated_concentration_filtrate_ub',
                        'ydatamin':'calculated_concentration_filtrate_min',
                        'ydatamax':'calculated_concentration_filtrate_max',
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'component_name'};
        data4_keys = ['analysis_id',
                      'experiment_id',
                      'sample_name_abbreviation',
                      'time_point',
                      'component_group_name',
                      'component_name',
                      'calculated_concentration_units',
                      'extracellular_percent',
                      'calculated_concentration_cv'
                    ];
        data4_nestkeys = ['component_name'];
        data4_keymap = {'xdata':'component_name',
                        'ydata':'calculated_concentration_average',
                        'ydatamean':'calculated_concentration_average',
                        'ydatalb':'calculated_concentration_lb',
                        'ydataub':'calculated_concentration_ub',
                        #'ydatamin':'calculated_concentration_min',
                        #'ydatamax':'calculated_concentration_max',
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'component_name'};
        # make the data object
        dataobject_O = [{"data":data_norm_broth,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_norm_filtrate,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_norm_combined,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_ave,"datakeys":data2_keys,"datanestkeys":data2_nestkeys},
                        {"data":data_ave,"datakeys":data3_keys,"datanestkeys":data3_nestkeys},
                        {"data":data_ave,"datakeys":data4_keys,"datanestkeys":data4_nestkeys}];
        # make the tile parameter objects for the normalized and averages
        formtileparameters_averages_O = {'tileheader':'Filter menu averages','tiletype':'html','tileid':"filtermenu2",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters_averages_O = {'htmlid':'filtermenuform2',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit2','text':'submit'},"formresetbuttonidtext":{'id':'reset2','text':'reset'},"formupdatebuttonidtext":{'id':'update2','text':'update'}};
        formtileparameters_averages_O.update(formparameters_averages_O);
        # make the svg objects for the averages data
        svgparameters_averages_broth_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data2_keymap,data1_keymap],
                            'svgid':'svg4',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
        		'svgformtileid':'filtermenu2','svgresetbuttonid':'reset2','svgsubmitbuttonid':'submit2'};
        svgtileparameters_averages_broth_O = {'tileheader':'Broth data','tiletype':'svg','tileid':"tile4",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        svgtileparameters_averages_broth_O.update(svgparameters_averages_broth_O);
        if data_norm_filtrate:
            svgparameters_averages_filtrate_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data3_keymap,data1_keymap],
                            'svgid':'svg5',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
        		'svgformtileid':'filtermenu2','svgresetbuttonid':'reset2','svgsubmitbuttonid':'submit2'};
            svgtileparameters_averages_filtrate_O = {'tileheader':'Filtrate data','tiletype':'svg','tileid':"tile5",'rowid':"row2",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
            svgtileparameters_averages_filtrate_O.update(svgparameters_averages_filtrate_O);
        else:
            svgparameters_averages_filtrate_O = {"svgtype":'boxandwhiskersplot2d_01',"svgkeymap":[data3_keymap],
                            'svgid':'svg5',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
        		'svgformtileid':'filtermenu2','svgresetbuttonid':'reset2','svgsubmitbuttonid':'submit2'};
            svgtileparameters_averages_filtrate_O = {'tileheader':'Filtrate data','tiletype':'svg','tileid':"tile5",'rowid':"row2",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
            svgtileparameters_averages_filtrate_O.update(svgparameters_averages_filtrate_O);
        svgparameters_averages_combined_O = {
                            #"svgtype":'boxandwhiskersplot2d_02',
                            "svgtype":'boxandwhiskersplot2d_01',
                            #"svgkeymap":[data4_keymap,data1_keymap],
                            "svgkeymap":[data4_keymap],
                            'svgid':'svg6',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
    						'svgformtileid':'filtermenu2','svgresetbuttonid':'reset2','svgsubmitbuttonid':'submit2'};
        svgtileparameters_averages_combined_O = {'tileheader':'Broth-Filtrate data','tiletype':'svg','tileid':"tile6",'rowid':"row2",'colid':"col3",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        svgtileparameters_averages_combined_O.update(svgparameters_averages_combined_O);
        # make the tables for the normalized and averages data
        tableparameters_normalized_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_normalized_O = {'tileheader':'normalized data','tiletype':'table','tileid':"tile7",'rowid':"row4",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_normalized_O.update(tableparameters_normalized_O);
        tableparameters_averages_O = {"tabletype":'responsivetable_01',
                    'tableid':'table2',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu2','tableresetbuttonid':'reset2','tablesubmitbuttonid':'submit2'};
        tabletileparameters_averages_O = {'tileheader':'averages data','tiletype':'table','tileid':"tile8",'rowid':"row5",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_averages_O.update(tableparameters_averages_O);
        parametersobject_O = [
            formtileparameters_averages_O,
            svgtileparameters_averages_broth_O,
            svgtileparameters_averages_filtrate_O,
            svgtileparameters_averages_combined_O,
            tabletileparameters_normalized_O,
            tabletileparameters_averages_O];
        tile2datamap_O = {
            "filtermenu2":[5],
            "tile4":[3,0],
            "tile5":[4,1],
            #"tile6":[5,2],
            "tile6":[5],
            "tile7":[2],
            "tile8":[5]
            };
        #if data_norm_filtrate: tile2datamap_O.update({"tile5":[4,1]})
        #else: tile2datamap_O.update({"tile5":[4]})
        filtermenuobject_O = [
            #{"filtermenuid":"filtermenu1","filtermenuhtmlid":"filtermenuform1",
            #"filtermenusubmitbuttonid":"submit1","filtermenuresetbuttonid":"reset1",
            #"filtermenuupdatebuttonid":"update1"},
            {"filtermenuid":"filtermenu2","filtermenuhtmlid":"filtermenuform2",
            "filtermenusubmitbuttonid":"submit2","filtermenuresetbuttonid":"reset2",
            "filtermenuupdatebuttonid":"update2"}
                              ];
        #
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
 def export_quantitationMethod_js(self,QMethod_id_I,component_names_I=[],data_dir_I='tmp'):
     '''Export the quantitation and calibrators to ddt'''
     #get the calibrator data
     data_1 = [];
     data_2 = [];
     data_1a = [];
     # get the sample names that were used to generate the calibration curve:
     if component_names_I:
         component_names = component_names_I;
     else:
         component_names = [];
         component_names = self.get_components(QMethod_id_I);
     for cn in component_names:
         # get the quant method parameters for each component
         fit,weighting,use_area = self.get_quantMethodParameters(QMethod_id_I,cn);
         # get the sample names for that component
         sample_names = [];
         sample_names = self.get_sampleNames_QMethodIDAndComponentNameAndSampleType(QMethod_id_I,cn,sample_type_I='Standard');
         if not sample_names: continue;
         concentrations = []
         ratios = [];
         for sn in sample_names:
             # get the quant method rows
             row = {};
             row = self.get_row_sampleNameAndComponentName(sn,cn);
             if row and not row is None and not row['concentration_ratio'] is None:
                 if use_area: row['ratio'] = row['area_ratio'];
                 else: row['ratio'] = row['height_ratio'];
                 row['acquisition_date_and_time'] = None;
                 data_1.append(row);
                 concentrations.append(row['concentration_ratio']);
                 ratios.append(row['ratio']);
         if not concentrations: continue;
         # get the quant method statistics
         row = {};
         row = self.get_row_QMethodIDAndComponentNamequantitationMethod(QMethod_id_I,cn);
         if row:
             data_2.append(row);
             # generate the line of best fit
             min_ratio = min(ratios);
             max_ratio = max(ratios);
             index_min = [cnt for cnt,x in enumerate(ratios) if x == min_ratio][0];
             index_max = [cnt for cnt,x in enumerate(ratios) if x == max_ratio][0];
             conc_min = min(concentrations);
             conc_max = max(concentrations);
             sample_name_min = sample_names[index_min];
             sample_name_max = sample_names[index_max];
             data_1a.append({'concentration_ratio':row['lloq'],
                     'ratio':min_ratio,
                     'component_name':cn,
                     'sample_name':sample_name_min,
                     'id':QMethod_id_I});
             data_1a.append({'concentration_ratio':row['uloq'],
                     'ratio':max_ratio,
                     'component_name':cn,
                     'sample_name':sample_name_max,
                     'id':QMethod_id_I});
             
     # dump chart parameters to a js files
     data1_keys = [
                 'id',
                 'concentration_ratio',
                 'sample_name',
                 'component_name',
                 'ratio',
                 ];
     data1_nestkeys = ['component_name'];
     data1_keymap = {'xdata':'concentration_ratio',
                     'ydata':'ratio',
                     'serieslabel':'component_name',
                     'featureslabel':'sample_name'};
     data2_keys = ['id',
                 'q1_mass',
                 'q3_mass',
                 'met_id',
                 'component_name',
                 'is_name',
                 'fit',
                 'weighting',
                 'intercept',
                 'slope',
                 'correlation',
                 'use_area',
                 'lloq',
                 'uloq',
                 'points',
                 ];
     data2_nestkeys = ['component_name'];
     data2_keymap = {'xdata':'concentration_ratio',
                     'ydata':'ratio',
                     'serieslabel':'component_name',
                     'featureslabel':None};
     parameters = {"chart1margin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                 "chart1width":500,"chart1height":350,
               "chart1title":"Metric Plot", "chart1x1axislabel":"sample_name","chart1y1axislabel":"measurement"}
     # make the data object
     dataobject_O = [{"data":data_1,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                     {"data":data_1a,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                     {"data":data_2,"datakeys":data2_keys,"datanestkeys":data2_nestkeys}];
     # make the tile parameter objects
     formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
     formparameters_O = {'htmlid':'filtermenuform1','htmltype':'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
     formtileparameters_O.update(formparameters_O);
     svgparameters_O = {"svgtype":'scatterlineplot2d_01',"svgkeymap":[data1_keymap,data1_keymap],
                         'svgid':'svg1',
                         "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                         "svgwidth":500,"svgheight":350,
                         "svgx1axislabel":"concentration_ratio","svgy1axislabel":"measurement_ratio",
 						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
     svgtileparameters_O = {'tileheader':'Regression','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
     svgtileparameters_O.update(svgparameters_O);
     tableparameters_O = {"tabletype":'responsivetable_01',
                 'tableid':'table1',
                 "tablefilters":None,
                 "tableclass":"table  table-condensed table-hover",
 			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
     tabletileparameters_O = {'tileheader':'Regression Statistics','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     tabletileparameters_O.update(tableparameters_O);
     parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
     tile2datamap_O = {"filtermenu1":[0],"tile2":[0,1],"tile3":[2]};
     # dump the data to a json file
     ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
         return data_json_O;
     with open(filename_str,'w') as file:
         file.write(ddtutilities.get_allObjects());
    def export_dataStage02PhysiologySampledPointsSubsystemsDescriptiveStats_js(self,analysis_id_I,plot_points_I=True,vertical_I=True,data_dir_I='tmp'):
        '''Export data for a box and whiskers plot
        INPUT:
        analysis_id_I = string,
        plot_points_I = boolean, default=False, raw data points will not be plotted on the same plot
        vertical_I = boolean, default=True, orient the boxes vertical as opposed to horizontal
        '''
        physiology_analysis_query=stage02_physiology_analysis_query(self.session,self.engine,self.settings);
        physiology_analysis_query.initialize_supportedTables();

        data_O = [];
        data_points_O = [];
        #get the analysis information
        simulation_ids = [];
        simulation_ids = physiology_analysis_query.get_simulationID_analysisID_dataStage02PhysiologyAnalysis(analysis_id_I);
        #get the data for the analysis
        if plot_points_I:
        #get the replicate data for the analysis
            #TODO... (copy code from above io function)
            #data_points_O = [];
            #data_points_O = quantification_dataPreProcessing_replicates_query.get_rowsAndSampleNameAbbreviations_analysisID_dataStage02QuantificationDataPreProcessingReplicates(analysis_id_I);
            for simulation in simulation_ids:
                data_tmp = self.get_rows_simulationID_dataStage02PhysiologySampledSubsystemData(simulation);
                data_O.extend(data_tmp);
        else:
            for simulation in simulation_ids:
                data_tmp = self.get_rows_simulationID_dataStage02PhysiologySampledSubsystemData(simulation);
                data_O.extend(data_tmp);
        # make the tile objects
        parametersobject_O = [];
        tile2datamap_O = {};
        filtermenuobject_O = [];
        dataobject_O = [];
        # dump chart parameters to a js files
        data1_keys = [
            #'analysis_id',
                      'simulation_id',
                      'simulation_dateAndTime',
                      'subsystem_id',
                      'flux_units',
                    ];
        data1_nestkeys = ['subsystem_id'];
        data2_keys = [
            #'analysis_id',
                      'simulation_id',
                      'simulation_dateAndTime',
                      'rxn_id',
                      'flux_units',
                    ];
        data2_nestkeys = ['subsystem_id'];
        if vertical_I:
            data1_keymap = {
                        'xdata':'subsystem_id',
                        'ydata':'sampling_ave',
                        'ydatamean':'sampling_ave',
                        'ydatalb':'sampling_lb',
                        'ydataub':'sampling_ub',
                        'ydatamin':'sampling_min',
                        'ydatamax':'sampling_max',
                        'ydataiq1':'sampling_iq_1',
                        'ydataiq3':'sampling_iq_3',
                        'ydatamedian':'sampling_median',
                        'serieslabel':'simulation_id',
                        'featureslabel':'subsystem_id'};
            data2_keymap = {
                        'xdata':'subsystem_id',
                        'ydata':'sampling_points',
                        'serieslabel':'simulation_id',
                        'featureslabel':'subsystem_id'};
        else:
            data1_keymap = {
                        'ydata':'subsystem_id',
                        'xdatamean':'sampling_ave',
                        'xdata':'sampling_ave',
                        'xdatalb':'sampling_lb',
                        'xdataub':'sampling_ub',
                        'xdatamin':'sampling_min',
                        'xdatamax':'sampling_max',
                        'xdataiq1':'sampling_iq_1',
                        'xdataiq3':'sampling_iq_3',
                        'xdatamedian':'sampling_median',
                        'serieslabel':'simulation_id',
                        'featureslabel':'subsystem_id'};
            data2_keymap = {
                        'ydata':'subsystem_id',
                        'xdata':'sampling_points',
                        'serieslabel':'simulation_id',
                        'featureslabel':'subsystem_id'};

        # make the data object
        dataobject_O.append({"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys});

        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        parametersobject_O.append(formtileparameters_O);
        if plot_points_I:
            tile2datamap_O.update({"filtermenu1":[1]});
        else:
            tile2datamap_O.update({"filtermenu1":[0]});
        
        #make the svg object
        if plot_points_I and vertical_I:
            dataobject_O.append({"data":data_points_O,"datakeys":data2_keys,"datanestkeys":data2_nestkeys});
            svgparameters_O = {"svgtype":'boxandwhiskersplot2d_02',
                               "svgkeymap":[data1_keymap,data2_keymap],
                                'svgid':'svg1',
                                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                                "svgwidth":500,"svgheight":350,
                                "svgx1axislabel":"subsystem_id",
                                "svgy1axislabel":"sampling points",
                                "svgdata2pointsradius":5.0,
    						    };
            svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({"tile2":[0,1]});
        elif not plot_points_I and vertical_I:
            svgparameters_O = {"svgtype":'boxandwhiskersplot2d_01',
                               "svgkeymap":[data1_keymap],
                                'svgid':'svg1',
                                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                                "svgwidth":500,"svgheight":350,
                                "svgx1axislabel":"subsystem_id","svgy1axislabel":"sampling points",
    						    'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
            svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({"tile2":[0]});
        elif plot_points_I and not vertical_I:
            dataobject_O.append({"data":data_points_O,"datakeys":data2_keys,"datanestkeys":data2_nestkeys});
            svgparameters_O = {"svgtype":'horizontalBoxAndWhiskersPlot2d_02',
                               "svgkeymap":[data1_keymap,data2_keymap],
                                'svgid':'svg1',
                                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                                "svgwidth":500,"svgheight":350,
                                "svgx1axislabel":"sampling points",
                                "svgy1axislabel":"rxn_id",
                                "svgdata2pointsradius":5.0,
    						    };
            svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({"tile2":[0,1]});
        elif not plot_points_I and not vertical_I:
            svgparameters_O = {"svgtype":'horizontalBoxAndWhiskersPlot2d_01',
                               "svgkeymap":[data1_keymap],
                                'svgid':'svg1',
                                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                                "svgwidth":500,"svgheight":350,
                                "svgx1axislabel":"sampling points",
                                "svgy1axislabel":"subsystem_id",
    						    'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
            svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({"tile2":[0]});

        #make the table object
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'descriptiveStats','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O.append(tabletileparameters_O);
        tile2datamap_O.update({"tile3":[0]});

        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
 def export_dataStage02IsotopomerFittedNetFluxDifferences_js(self,analysis_id_I = None,data_dir_I="tmp"):
     '''Plot the flux differences and fold_change as bar plots for a given analysis
     
     Input:
     analysis_id_I = string
     data_dir_I = output .js file directory and filename
     
     DDT tiles:
     1. filter menu
     2. horizontal bar plot of flux differences
     3. horizontal bar plot of flux fold_change
     4. table
     '''
     
     # get the data
     data_O =[]; 
     flux_data = [];
     flux_data = self.get_rows_analysisID_dataStage02IsotopomerFittedNetFluxDifferences(analysis_id_I);
     # convert dataAndTime to string types
     for i,row in enumerate(flux_data):
         row['simulation_dateAndTime_1'] = self.convert_datetime2string(row['simulation_dateAndTime_1']);
         row['simulation_dateAndTime_2'] = self.convert_datetime2string(row['simulation_dateAndTime_2']);
         #row['flux_units'] = row['flux_units'].replace('*','x');
         if row['significant']: row['significant'] = 'Yes';
         else: row['significant'] = 'No';
         data_O.append(row);
     # dump chart parameters to a js files
     data1_keys = ['simulation_id_1','simulation_dateAndTime_1','simulation_id_2','simulation_dateAndTime_2','rxn_id','flux_units','significant'
                 ];
     data1_nestkeys = ['rxn_id'];
     data1_keymap = {'xdata':'flux_distance',
                     'ydata':'rxn_id',
                     'serieslabel':'simulation_id_2',
                     'featureslabel':'rxn_id'
                     };
     data2_keymap = {'xdata':'fold_change_geo',
                     'ydata':'rxn_id',
                     'serieslabel':'simulation_id_2',
                     'featureslabel':'rxn_id'
                     };
     # make the data object
     dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
     # make the tile parameter objects
     # tile 1: form (row 1, col1)
     formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
     formtileparameters_O.update(formparameters_O);
     # tile 2: vertical bars plot of the flux_difference (row 2, col 1)
     svgparameters1_O = {"svgtype":'horizontalbarschart2d_01',"svgkeymap":[data1_keymap],
                         'svgid':'svg1',
                         "svgmargin":{ 'top': 50, 'right': 250, 'bottom': 50, 'left': 50 },
                         "svgwidth":350,"svgheight":900,
                         "svgx1axislabel":"flux_distance","svgy1axislabel":"rxn_id",
 						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
     svgtileparameters1_O = {'tileheader':'Flux distance','tiletype':'svg','tileid':"tile1",'rowid':"row2",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
     svgtileparameters1_O.update(svgparameters1_O);
     # tile 3: vertical bars plot of the flux_difference (row 2, col 2)
     svgparameters2_O = {"svgtype":'horizontalbarschart2d_01',"svgkeymap":[data2_keymap],
                         'svgid':'svg2',
                         "svgmargin":{ 'top': 50, 'right': 250, 'bottom': 50, 'left': 50 },
                         "svgwidth":350,"svgheight":900,
                         "svgx1axislabel":"fold_change","svgy1axislabel":"rxn_id",
 						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
     svgtileparameters2_O = {'tileheader':'Fold change','tiletype':'svg','tileid':"tile2",'rowid':"row2",'colid':"col2",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
     svgtileparameters2_O.update(svgparameters2_O);
     # tile 4: table of data (row 3, col 1)
     tableparameters_O = {"tabletype":'responsivetable_01',
                 'tableid':'table1',
                 "tablefilters":None,
                 "tableclass":"table  table-condensed table-hover",
 			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
     tabletileparameters_O = {'tileheader':'Flux difference','tiletype':'table','tileid':"tile3",'rowid':"row3",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     tabletileparameters_O.update(tableparameters_O);
     parametersobject_O = [formtileparameters_O,
                           svgtileparameters1_O,
                           svgtileparameters2_O,
                           tabletileparameters_O];
     tile2datamap_O = {"filtermenu1":[0],
                       "tile1":[0],
                       "tile2":[0],
                       "tile3":[0]};
     # dump the data to a json file
     data_str = 'var ' + 'data' + ' = ' + json.dumps(dataobject_O) + ';';
     parameters_str = 'var ' + 'parameters' + ' = ' + json.dumps(parametersobject_O) + ';';
     tile2datamap_str = 'var ' + 'tile2datamap' + ' = ' + json.dumps(tile2datamap_O) + ';';
     ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
         return data_json_O;
     with open(filename_str,'w') as file:
         file.write(ddtutilities.get_allObjects());
    def export_visualizationProject_js(self,project_id_I,data_dir_I="tmp"):
        """export visualization_project for visualization"""

        print("exporting visualization_project...")

        # query the project info
        data1_project = {};
        data1_project = self.get_project_projectID_visualizationProject(project_id_I);
        data1_O = [];
        data1_O = self.get_rows_projectID_visualizationProject(project_id_I);
        # query the project description
        data2_O = [];
        data2_O = self.get_rows_projectID_visualizationProjectDescription(project_id_I);
        # query the project status
        data3_O = [];
        data3_O = self.get_rows_projectID_visualizationProjectStatus(project_id_I);
        # data parameters
        data1_keys = ['analysis_id','data_export_id','pipeline_id'#,'container_export_id'
                      ];
        data1_nestkeys = ['data_export_id'];
        data1_keymap = {'buttonparameter':'data_export_id','liparameter':'analysis_id',
                        'buttontext':'data_export_id','litext':'analysis_id'};
        data2_keys = ['project_id','project_section','project_heading','project_tileorder'
                      ];
        data2_nestkeys = ['project_id'];
        data2_keymap = {'htmlmediasrc':'project_media','htmlmediaalt':'',
                        'htmlmediahref':'project_href','htmlmediaheading':'project_heading',
                        'htmlmediaparagraph':'project_paragraph'};
        data3_keys = ['project_id','pipeline_id','pipeline_progress'
                      ];
        data3_nestkeys = ['pipeline_id'];
        data3_keymap = {
                #'xdata':'pipeline_id',
                #'ydata':'pipeline_progress',
                'xdata':'pipeline_progress',
                'ydata':'pipeline_id',
                'serieslabel':'pipeline_id',
                'featureslabel':'pipeline_id',
                'ydatalb':None,
                'ydataub':None};

        # make the data, parameters, and tile2datamap variables:
        dataobject_O = [];
        parametersobject_O = [];
        tile2datamap_O = {};
        tile_cnt = 0;
        row_cnt = 1;
        # project_status:
        if data3_O:
            cnt = 1;
            tileid = "tile" + str(tile_cnt);
            colid = "col" + str(cnt);
            rowid = "row" + str(row_cnt);

            # make the tile parameter objects
            # tile 0: form
            formtileparameters_O = {
                'tileheader':'Filter menu',
                'tiletype':'html',
                'tileid':"filtermenu1",
                'rowid':rowid,
                'colid':colid,
                'tileclass':"panel panel-default",
                'rowclass':"row",
                'colclass':"col-sm-4"};
            formparameters_O = {
                'htmlid':'filtermenuform1',
                'htmltype':'form_01',
                "formsubmitbuttonidtext":{'id':'submit1','text':'submit'},
                "formresetbuttonidtext":{'id':'reset1','text':'reset'},
                "formupdatebuttonidtext":{'id':'update1','text':'update'}
                };
            formtileparameters_O.update(formparameters_O);
            dataobject_O.append({"data":data3_O,"datakeys":data3_keys,"datanestkeys":data3_nestkeys});
            parametersobject_O.append(formtileparameters_O);
            tile2datamap_O.update({"filtermenu1":[tile_cnt]});
            cnt+=1;
            
            svgtileid = "tilesvg"+str(tile_cnt);
            svgid = 'svg'+str(tile_cnt);
            colid = "col" + str(cnt);
            # make the svg object
            svgparameters1_O = {
                #"svgtype":'verticalpieschart2d_01',
                #"svgtype":'verticalbarschart2d_01',
                "svgtype":'horizontalbarschart2d_01',
                "svgkeymap":[data3_keymap],
                'svgid':'svg'+str(cnt),
                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 150 },
                "svgwidth":350,
                "svgheight":250,
                "svgy1axislabel":"fraction"            
                    };
            svgtileparameters1_O = {
                'tileheader':'Project status',
                'tiletype':'svg',
                'tileid':svgtileid,
                'rowid':rowid,
                'colid':colid,
                'tileclass':"panel panel-default",
                'rowclass':"row",
                'colclass':"col-sm-8"};
            svgtileparameters1_O.update(svgparameters1_O);
            parametersobject_O.append(svgtileparameters1_O);
            tile2datamap_O.update({svgtileid:[tile_cnt]});
            tile_cnt+=1;
            row_cnt+=1;
        # project_description:
        if data2_O:
            for i,d in enumerate(data2_O):
                tileid = "tile" + str(tile_cnt);
                colid = "col" + str(i);
                rowid = "row" + str(row_cnt);
                tileheader = d['project_section'];
                htmlid = "html" + str(tile_cnt);
                tileparameters = {'tileheader':tileheader,'tiletype':'html','tileid':tileid,'rowid':rowid,'colid':colid,
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
                htmlparameters={"htmlkeymap":[data2_keymap],
                            'htmltype':'media_01','htmlid':htmlid};
                tileparameters.update(htmlparameters);
                parametersobject_O.append(tileparameters);
                dataobject_O.append({"data":[d],"datakeys":data2_keys,"datanestkeys":data2_nestkeys});
                tile2datamap_O.update({tileid:[tile_cnt]});
                tile_cnt+=1;
            row_cnt+=1;
        # project:
        if data1_project:
            data1_dict = {};
            for data_export_id in data1_project['data_export_id']:
                data1_dict[data_export_id]=[];
            for d in data1_O:
                data1_dict[d['data_export_id']].append(d);
            data1_keys = list(data1_dict.keys());
            data1_keys.sort();
            col_cnt = 0;
            #for k,v in data1_dict.iteritems():
            for k in data1_keys:
                tileid = "tile" + str(tile_cnt);
                colid = "col" + str(col_cnt);
                rowid = "row" + str(row_cnt);
                tileheader = data1_dict[k][0]['pipeline_id'];
                htmlid = "html" + str(tile_cnt);
                #tileparameters = {'tileheader':tileheader,'tiletype':'html','tileid':tileid,'rowid':"row2",'colid':colid,
                #    'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
                #hrefparameters = {"hrefurl":'project.html',"htmlkeymap":[data1_keymap],
                #                'htmltype':'href_01','htmlid':htmlid};
                tileparameters = {'tileheader':tileheader,'tiletype':'html','tileid':tileid,'rowid':rowid,'colid':colid,
                    'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6","formsubmitbuttonidtext":{'id':'submit1','text':'submit'}};
                hrefparameters = {"hrefurl":'project.html',"htmlkeymap":[data1_keymap],
                                'htmltype':'href_02','htmlid':htmlid};
                tileparameters.update(hrefparameters);
                parametersobject_O.append(tileparameters);
                dataobject_O.append({"data":data1_dict[k],"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
                tile2datamap_O.update({tileid:[tile_cnt]});
                tile_cnt+=1;
                col_cnt+=1;
                
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage02PhysiologyGraphDataShortestPathStats_js(self,
                analysis_id_I,
                plot_points_I=False,
                vertical_I=True,
                data_dir_I='tmp'):
        '''export descriptive stats of shortest paths'''
        
        data_O = [];
        data_points_O = [];
        if plot_points_I:
        #get the replicate data for the analysis
            #TODO... (copy code from above io function)
            #data_points_O = [];
            #data_points_O = quantification_dataPreProcessing_replicates_query.get_rowsAndSampleNameAbbreviations_analysisID_dataStage02QuantificationDataPreProcessingReplicates(analysis_id_I);
            data_tmp = self.get_rows_analysisID_dataStage02PhysiologyGraphDataShortestPathStats(analysis_id_I);
            for d in data_tmp:
                d['path_id'] = d['path_start'] + '-->' + d['path_stop']
                if np.isnan(d['path_ci_lb']):d['path_ci_lb']=d['path_average'];
                if np.isnan(d['path_ci_ub']):d['path_ci_ub']=d['path_average'];
                data_O.append(d);
        else:
            data_tmp = self.get_rows_analysisID_dataStage02PhysiologyGraphDataShortestPathStats(analysis_id_I);
            for d in data_tmp:
                d['path_id'] = d['path_start'] + '-->' + d['path_stop']
                if np.isnan(d['path_ci_lb']):d['path_ci_lb']=d['path_average'];
                if np.isnan(d['path_ci_ub']):d['path_ci_ub']=d['path_average'];
                data_O.append(d);
        # make the tile objects
        parametersobject_O = [];
        tile2datamap_O = {};
        filtermenuobject_O = [];
        dataobject_O = [];
        # dump chart parameters to a js files
        data1_keys = [
            #'analysis_id',
                      'simulation_id',
                      'path_start',
                      'path_stop',
                      'algorithm',
                    ];
        data1_nestkeys = ['path_id'];
        data2_keys = [
            #'analysis_id',
                      'simulation_id',
                      'path_start',
                      'path_stop',
                      'algorithm',
                    ];
        data2_nestkeys = ['path_id'];
        if vertical_I:
            data1_keymap = {
                        'xdata':'path_id',
                        'ydata':'path_average',
                        'ydatamean':'path_average',
                        'ydatalb':'path_ci_lb',
                        'ydataub':'path_ci_ub',
                        'ydatamin':'path_min',
                        'ydatamax':'path_max',
                        'ydataiq1':'path_iq_1',
                        'ydataiq3':'path_iq_3',
                        'ydatamedian':'path_median',
                        'serieslabel':'simulation_id',
                        #'serieslabel':'algorithm',
                        'featureslabel':'path_id'};
            data2_keymap = {
                        'xdata':'path_id',
                        'ydata':'path_length',
                        'serieslabel':'simulation_id',
                        #'serieslabel':'algorithm',
                        'featureslabel':'path_id'};
        else:
            data1_keymap = {
                        'ydata':'path_id',
                        'xdatamean':'path_average',
                        'xdata':'path_average',
                        'xdatalb':'path_ci_lb',
                        'xdataub':'path_ci_ub',
                        'xdatamin':'path_min',
                        'xdatamax':'path_max',
                        'xdataiq1':'path_iq_1',
                        'xdataiq3':'path_iq_3',
                        'xdatamedian':'path_median',
                        #'serieslabel':'simulation_id',
                        'serieslabel':'algorithm',
                        'featureslabel':'path_id'};
            data2_keymap = {
                        'ydata':'path_id',
                        'xdata':'path_length',
                        #'serieslabel':'simulation_id',
                        'serieslabel':'algorithm',
                        'featureslabel':'path_id'};

        # make the data object
        dataobject_O.append({"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys});

        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        parametersobject_O.append(formtileparameters_O);
        if plot_points_I:
            tile2datamap_O.update({"filtermenu1":[1]});
        else:
            tile2datamap_O.update({"filtermenu1":[0]});
        
        #make the svg object
        if plot_points_I and vertical_I:
            dataobject_O.append({"data":data_points_O,"datakeys":data2_keys,"datanestkeys":data2_nestkeys});
            svgparameters_O = {"svgtype":'boxandwhiskersplot2d_02',
                               "svgkeymap":[data1_keymap,data2_keymap],
                                'svgid':'svg1',
                                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                                "svgwidth":500,"svgheight":350,
                                "svgx1axislabel":"path id",
                                "svgy1axislabel":"path length",
                                "svgdata2pointsradius":5.0,
    						    };
            svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({"tile2":[0,1]});
        elif not plot_points_I and vertical_I:
            svgparameters_O = {"svgtype":'boxandwhiskersplot2d_01',
                               "svgkeymap":[data1_keymap],
                                'svgid':'svg1',
                                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                                "svgwidth":500,"svgheight":350,
                                "svgx1axislabel":"path id",
                                "svgy1axislabel":"path length",
    						    'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
            svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({"tile2":[0]});
        elif plot_points_I and not vertical_I:
            dataobject_O.append({"data":data_points_O,"datakeys":data2_keys,"datanestkeys":data2_nestkeys});
            svgparameters_O = {"svgtype":'horizontalBoxAndWhiskersPlot2d_02',
                               "svgkeymap":[data1_keymap,data2_keymap],
                                'svgid':'svg1',
                                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                                "svgwidth":500,"svgheight":350,
                                "svgx1axislabel":"path length",
                                "svgy1axislabel":"path id",
                                "svgdata2pointsradius":5.0,
    						    };
            svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({"tile2":[0,1]});
        elif not plot_points_I and not vertical_I:
            svgparameters_O = {"svgtype":'horizontalBoxAndWhiskersPlot2d_01',
                               "svgkeymap":[data1_keymap],
                                'svgid':'svg1',
                                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                                "svgwidth":500,"svgheight":350,
                                "svgx1axislabel":"path length",
                                "svgy1axislabel":"path id",
    						    'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
            svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({"tile2":[0]});

        #make the table object
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'descriptiveStats','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O.append(tabletileparameters_O);
        tile2datamap_O.update({"tile3":[0]});

        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);

        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01AleTrajectories_js(self,analysis_id_I,fit_func_I='lowess',data_dir_I="tmp"):
        """export data_stage01_ale_trajectories for visualization"""

        print("exporting data_stage01_ale_trajectories...")

        calc = calculate_smoothingFunctions();

        # query the analysis info
        experiment_ids,ale_ids = [],[];
        experiment_ids,ale_ids = self.get_experimentIDAndALEID_analysisID_dataStage01ResequencingAnalysis(analysis_id_I);
        # collect the data and calculate the fitted trajectories
        data_O = []; 
        data1_O={};
        data2_O={};
        data1_O['ale_time'] = [];
        data1_O['generations'] = [];
        data1_O['ccd'] = [];
        data2_O['ale_time'] = [];
        data2_O['generations'] = [];
        data2_O['ccd'] = [];
        for sna_cnt,sna in enumerate(ale_ids):
            #query growth rates and times
            growth_rates = [];
            growth_rates = self.get_rows_experimentIDAndALEID_dataStage01AleTrajectories(experiment_ids[sna_cnt],sna)
            ale_time_units = growth_rates[0]['ale_time_units'];
            rate_units = growth_rates[0]['rate_units'];
            # parse out the data for each ale_id
            x,x_g,x_ccd,y=[],[],[],[];
            for k in growth_rates:
                x.append(k['ale_time'])
                x_g.append(k['generations'])
                x_ccd.append(k['ccd'])
                y.append(k['rate'])
                data1_O['ale_time'].append({'ale_id':sna,
                               'ale_time':k['ale_time'],
                               'ale_time_units':ale_time_units,
                               'rate':k['rate'],
                               'rate_units':rate_units,
                               'used_':True,
                               'comment_':k['comment_']});
                data1_O['generations'].append({'ale_id':sna,
                               'generations':k['generations'],
                               'rate':k['rate'],
                               'rate_units':rate_units,
                               'used_':True,
                               'comment_':k['comment_']});
                data1_O['ccd'].append({'ale_id':sna,
                               'ccd':k['ccd'],
                               'rate':k['rate'],
                               'rate_units':rate_units,
                               'used_':True,
                               'comment_':k['comment_']});
                data_O.append({'ale_id':sna,
                               'ale_time':k['ale_time'],
                               'ale_time_units':ale_time_units,
                               'generations':k['generations'],
                               'ccd':k['ccd'],
                               'rate':k['rate'],
                               'rate_units':rate_units,
                               'used_':True,
                               'comment_':k['comment_']});
            # generate the fitted data for ale_time
            x_fit,y_fit=[],[];
            x_fit,y_fit=calc.fit_trajectories(x,y,fit_func_I,plot_fit_I=False);
            # restructure into input for d3
            for i,x in enumerate(x_fit):
                data2_O['ale_time'].append({'ale_id':sna,
                               'ale_time':x_fit[i],
                               'ale_time_units':ale_time_units,
                               'rate':y_fit[i],
                               'rate_units':rate_units,
                               'used_':True,
                               'comment_':None});
            # generate the fitted data for generations
            x_g_fit,y_g_fit=[],[];
            x_g_fit,y_g_fit=calc.fit_trajectories(x_g,y,fit_func_I,plot_fit_I=False);
            # restructure into input for d3
            for i,x in enumerate(x_g_fit):
                data2_O['generations'].append({'ale_id':sna,
                               'generations':x_g_fit[i],
                               'rate':y_g_fit[i],
                               'rate_units':rate_units,
                               'used_':True,
                               'comment_':None});
            # generate the fitted data for ccd
            x_ccd_fit,y_ccd_fit=[],[];
            x_ccd_fit,y_ccd_fit=calc.fit_trajectories(x_ccd,y,fit_func_I,plot_fit_I=False);
            # restructure into input for d3
            for i,x in enumerate(x_ccd_fit):
                data2_O['ccd'].append({'ale_id':sna,
                               'ccd':x_ccd_fit[i],
                               'rate':y_ccd_fit[i],
                               'rate_units':rate_units,
                               'used_':True,
                               'comment_':None});

        #initialize ddt objects
        dataobject_O = [];
        parametersobject_O = [];
        tile2datamap_O = {};
        filtermenuobject_O=None;
        # make the tile parameter objects
        # tile 1: form
        formtileparameters_O = {
            'tileheader':'Filter menu',
            'tiletype':'html',
            'tileid':"filtermenu1",
            'rowid':"row1",
            'colid':"col1",
            'tileclass':"panel panel-default",
            'rowclass':"row",
            'colclass':"col-sm-4"};
        formparameters_O = {
            "htmltype":'form_01',
            "formsubmitbuttonidtext":{'id':'submit1','text':'submit'},
            "formresetbuttonidtext":{'id':'reset1','text':'reset'},
            "formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        parametersobject_O.append(formtileparameters_O)
        data1_keys = ['ale_id'];
        data1_nestkeys = ['ale_id'];
        data1_keymap = {'xdata':'ale_time','ydata':'rate','serieslabel':'ale_id','featureslabel':''};
        dataobject_O.append({"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
        tile2datamap_O.update({"filtermenu1":[0]});
        
        # tile 2-4: trajectors for ale_time, generations, and CCDs
        cnt = 1;
        data_cnt = 1;
        for k in data1_O.keys():
            tileid = "tile"+str(cnt);
            svgid = "svg"+str(cnt);
            colid = "col"+str(cnt+1);
            if k=='ale_time':
                svgx1axislabel = "time (days)";
            else:
                svgx1axislabel = k;
            data1_keys = ['ale_id'];
            data1_nestkeys = ['ale_id'];
            data1_keymap = {
                'xdata':k,
                'ydata':'rate',
                'serieslabel':'ale_id',
                'featureslabel':''};
            dataobject_O.append({"data":data1_O[k],"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
            dataobject_O.append({"data":data2_O[k],"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
            svgparameters_O = {
                "svgtype":'scatterlineplot2d_01',
                "svgkeymap":[data1_keymap,data1_keymap],
                'svgid':svgid,
                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                "svgwidth":500,"svgheight":350,
                "svgx1axislabel":svgx1axislabel,
                "svgy1axislabel":"growth rate (hr-1)",
                };
            svgtileparameters_O = {
                'tileheader':'ALE trajectories',
                'tiletype':'svg',
                'tileid':tileid,
                'rowid':"row1",
                'colid':colid,
                'tileclass':"panel panel-default",
                'rowclass':"row",
                'colclass':"col-sm-8"};
            svgtileparameters_O.update(svgparameters_O);
            parametersobject_O.append(svgtileparameters_O);
            tile2datamap_O.update({tileid:[data_cnt,data_cnt+1]});
            data_cnt+=2;
            cnt+=1;

        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01IsotopomerNormalized_js(self,experiment_id_I,sample_names_I=[],sample_name_abbreviations_I=[],time_points_I=[],scan_types_I=[],met_ids_I=[],data_dir_I="tmp",
                                                  single_plot_I = True):
        """Export data_stage01_isotopomer_normalized to js file"""

        mids = mass_isotopomer_distributions();

        # get the data
        
        data_O = [];
        data_dict_O = {};
        sample_names_O = [];
        # get time points
        if time_points_I:
            time_points = time_points_I;
        else:
            time_points = self.get_timePoint_experimentID_dataStage01Normalized(experiment_id_I);
        for tp in time_points:
            print('Plotting precursor and product spectrum from isotopomer normalized for time-point ' + str(tp));
            if sample_names_I:
                sample_abbreviations = [];
                sample_types = ['Unknown','QC'];
                sample_types_lst = [];
                for sn in sample_names_I:
                    for st in sample_types:
                        sample_abbreviations_tmp = [];
                        sample_abbreviations_tmp = self.get_sampleNameAbbreviations_experimentIDAndSampleTypeAndTimePointAndSampleName_dataStage01Normalized(experiment_id_I,st,tp,sn);
                        sample_abbreviations.extend(sample_abbreviations_tmp);
                        sample_types_lst.extend([st for i in range(len(sample_abbreviations_tmp))]);
            elif sample_name_abbreviations_I:
                sample_abbreviations = [];
                sample_types = ['Unknown','QC'];
                sample_types_lst = [];
                for sn in sample_name_abbreviations_I:
                    for st in sample_types:
                        sample_abbreviations_tmp = [];
                        sample_abbreviations_tmp = self.get_sampleNameAbbreviations_experimentIDAndSampleTypeAndTimePointAndSampleNameAbbreviation_dataStage01Normalized(experiment_id_I,st,tp,sn);
                        sample_abbreviations.extend(sample_abbreviations_tmp);
                        sample_types_lst.extend([st for i in range(len(sample_abbreviations_tmp))]);
                # query sample types from sample name abbreviations and time-point from data_stage01_isotopomer_normalized 
            else:
                # get sample names and sample name abbreviations
                sample_abbreviations = [];
                sample_types = ['Unknown','QC'];
                sample_types_lst = [];
                for st in sample_types:
                    sample_abbreviations_tmp = [];
                    sample_abbreviations_tmp = self.get_sampleNameAbbreviations_experimentIDAndSampleTypeAndTimePoint_dataStage01Normalized(experiment_id_I,st,tp);
                    sample_abbreviations.extend(sample_abbreviations_tmp);
                    sample_types_lst.extend([st for i in range(len(sample_abbreviations_tmp))]);
            for sna_cnt,sna in enumerate(sample_abbreviations):
                print('Plotting precursor and product spectrum from isotopomer normalized for sample name abbreviation ' + sna);
                # get the scan_types
                if scan_types_I:
                    scan_types = [];
                    scan_types_tmp = [];
                    scan_types_tmp = self.get_scanTypes_experimentIDAndTimePointAndSampleAbbreviationsAndSampleType_dataStage01Normalized(experiment_id_I,tp,sna,sample_types_lst[sna_cnt]);
                    scan_types = [st for st in scan_types_tmp if st in scan_types_I];
                else:
                    scan_types = [];
                    scan_types = self.get_scanTypes_experimentIDAndTimePointAndSampleAbbreviationsAndSampleType_dataStage01Normalized(experiment_id_I,tp,sna,sample_types_lst[sna_cnt]);
                for scan_type in scan_types:
                    print('Plotting precursor and product spectrum for scan type ' + scan_type)
                    # met_ids
                    if not met_ids_I:
                        met_ids = [];
                        met_ids = self.get_metIDs_experimentIDAndSampleAbbreviationAndTimePointAndSampleTypeAndScanType_dataStage01Normalized( \
                                experiment_id_I,sna,tp,sample_types_lst[sna_cnt],scan_type);
                    else:
                        met_ids = met_ids_I;
                    if not(met_ids): continue #no component information was found
                    for met in met_ids:
                        print('Plotting precursor and product spectrum for metabolite ' + met);
                        if sample_names_I:
                            sample_names = sample_names_I;
                        else:
                            sample_names,replicate_numbers,sample_types = [],[],[];
                            sample_names,replicate_numbers,sample_types = self.get_sampleNamesAndReplicateNumbersAndSampleTypes_experimentIDAndSampleNameAbbreviationAndMetIDAndTimePointAndScanType_dataStage01Normalized( \
                                experiment_id_I,sna,met,tp,scan_type);
                        if not(replicate_numbers): continue; #no replicates found
                        for rep_cnt,rep in enumerate(replicate_numbers):
                        #if not(sample_names): continue; #no replicates found
                        #for sn_cnt,sn in enumerate(sample_names):
                            print('Plotting precursor and product spectrum for replicate_number ' + str(rep));
                            #print('Plotting precursor and product spectrum for sample_name ' + sn);
                            #sample_names_O.append(sn);
                            #get data
                            peakData_I = {};
                            peakData_I = self.get_dataNormalized_experimentIDAndSampleAbbreviationAndTimePointAndScanTypeAndMetIDAndReplicateNumber_dataStage01Normalized( \
                                experiment_id_I,sna,tp,scan_type,met,rep);
                            #peakData_I = self.get_dataNormalized_experimentIDAndSampleAbbreviationAndTimePointAndScanTypeAndMetIDAndSampleName_dataStage01Normalized( \
                            #    experiment_id_I,sna,tp,scan_type,met,sn);
                            if peakData_I:
                                data_sample_names_tmp=[];
                                fragment_formulas = list(peakData_I.keys());
                                peakSpectrum_corrected, peakSpectrum_normalized = mids.extract_peakList_normMax(\
                                    peakData_I, fragment_formulas, True);
                                for fragment_formula in fragment_formulas:
                                    for fragment_mass,intensity_normalized in peakSpectrum_normalized[fragment_formula].items():
                                        sample_name = sna + "_" + str(rep);
                                        sample_names_O.append(sample_name);
                                        fragment_id = mids.make_fragmentID(met,fragment_formula,fragment_mass);
                                        intensity = 0.0;
                                        if intensity_normalized:
                                            intensity = intensity_normalized;
                                        data_tmp = {
                                                    'experiment_id':experiment_id_I,
                                                    'sample_name':sample_name,
                                                    #'sample_name':sn,
                                                    'sample_name_abbreviation':sna,
                                                    'sample_type':sample_types_lst[sna_cnt],
                                                    'time_point':tp,
                                                    #'dilution':dil,
                                                    'replicate_number':rep,
                                                    'met_id':met,
                                                    'fragment_formula':fragment_formula,
                                                    'fragment_mass':fragment_mass,
                                                    'intensity_normalized':intensity,
                                                    'intensity_normalized_units':"normMax",
                                                    'scan_type':scan_type,
                                                    'fragment_id':fragment_id};
                                        data_O.append(data_tmp);
                                        if not sample_name in data_dict_O.keys():
                                            data_dict_O[sample_name] = [];
                                            data_dict_O[sample_name].append(data_tmp);
                                        else:
                                            data_dict_O[sample_name].append(data_tmp);

        # record the unique sample names:
        sample_names_unique = list(set(sample_names_O));
        sample_names_unique.sort();

        # get the table data
        data_table_O = [];
        if time_points_I:
            time_points = time_points_I;
        else:
            time_points = self.get_timePoint_experimentID_dataStage01Normalized(experiment_id_I);
        for tp in time_points:
            print('Tabulating precursor and product spectrum from isotopomer normalized for time-point ' + str(tp));
            dataListUpdated = [];
            # get dilutions
            dilutions = [];
            dilutions = self.get_sampleDilution_experimentIDAndTimePoint_dataStage01Normalized(experiment_id_I,tp);
            for dil in dilutions:
                print('Tabulating precursor and product spectrum from isotopomer normalized for dilution ' + str(dil));
                if sample_names_I:
                    sample_abbreviations = [];
                    sample_types = ['Unknown','QC'];
                    for sn in sample_names_I:
                        for st in sample_types:
                            sample_abbreviations_tmp = [];
                            sample_abbreviations_tmp = self.get_sampleNameAbbreviations_experimentIDAndSampleTypeAndTimePointAndDilutionAndSampleName_dataStage01Normalized(experiment_id_I,st,tp,dil,sn);
                            sample_abbreviations.extend(sample_abbreviations_tmp);
                elif sample_name_abbreviations_I:
                    sample_abbreviations = sample_name_abbreviations_I;
                else:
                    # get sample names and sample name abbreviations
                    sample_abbreviations = [];
                    sample_types = ['Unknown','QC'];
                    for st in sample_types:
                        sample_abbreviations_tmp = [];
                        sample_abbreviations_tmp = self.get_sampleNameAbbreviations_experimentIDAndSampleTypeAndTimePointAndDilution_dataStage01Normalized(experiment_id_I,st,tp,dil);
                        sample_abbreviations.extend(sample_abbreviations_tmp);
                for sna_cnt,sna in enumerate(sample_abbreviations):
                    print('Tabulating precursor and product spectrum from isotopomer normalized for sample name abbreviation ' + sna);
                    # get the scan_types
                    if scan_types_I:
                        scan_types = scan_types_I;
                    else:
                        scan_types = [];
                        scan_types = self.get_scanTypes_experimentIDAndTimePointAndDilutionAndSampleAbbreviations_dataStage01Normalized(experiment_id_I,tp,dil,sna);
                    for scan_type in scan_types:
                        print('Tabulting precursor and product spectrum for scan type ' + scan_type)
                        # met_ids
                        if not met_ids_I:
                            met_ids = [];
                            met_ids = self.get_metIDs_experimentIDAndSampleAbbreviationAndTimePointAndDilutionAndScanType_dataStage01Normalized( \
                                    experiment_id_I,sna,tp,dil,scan_type);
                        else:
                            met_ids = met_ids_I;
                        if not(met_ids): continue #no component information was found
                        for met in met_ids:
                            # get the data
                            data = [];
                            data = self.get_rows_experimentIDAndSampleAbbreviationAndTimePointAndDilutionAndScanTypeAndMetID_dataStage01Normalized( \
                                    experiment_id_I,sna,tp,dil,scan_type,met);
                            for d in data:
                                d['sample_name'] = d['sample_name_abbreviation']+"_"+str(d['replicate_number']);
                                d['fragment_id'] = mids.make_fragmentID(d['met_id'],d['fragment_formula'],d['fragment_mass']);
                            data_table_O.extend(data);
        # visualization parameters
        data1_keys = ['sample_name','sample_name_abbreviation',
                      'sample_type',
                      'met_id','time_point','fragment_formula','fragment_mass','scan_type','fragment_id'];
        data1_nestkeys = [
            #'fragment_id',
            'fragment_mass'
            ];
        data1_keymap = {
                #'xdata':'fragment_id',
                'xdata':'fragment_mass',
                'ydata':'intensity_normalized',
                'serieslabel':'scan_type',
                #'serieslabel':'sample_name', #single plot
                #'featureslabel':'fragment_id',
                'featureslabel':'fragment_mass',
                'tooltipdata':'sample_name_abbreviation',
                'ydatalb':None,
                'ydataub':None};

        # initialize the ddt objects
        dataobject_O = [];
        parametersobject_O = [];
        tile2datamap_O = {};

        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        dataobject_O.append({"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
        parametersobject_O.append(formtileparameters_O);
        tile2datamap_O.update({"filtermenu1":[0]});
        if not single_plot_I:
            rowcnt = 1;
            colcnt = 1;
            cnt = 0;
            for sn in sample_names_unique:
                svgtileid = "tilesvg"+str(cnt);
                svgid = 'svg'+str(cnt);
                iter=cnt+1; #start at 1
                if (cnt % 2 == 0): 
                    rowcnt = rowcnt+1;#even 
                    colcnt = 1;
                else:
                    colcnt = colcnt+1;
                # make the svg object
                svgparameters1_O = {"svgtype":'verticalbarschart2d_01',"svgkeymap":[data1_keymap],
                    #'svgid':'svg1',
                    'svgid':'svg'+str(cnt),
                    "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                    "svgwidth":350,"svgheight":250,"svgy1axislabel":"intensity (norm)",            
                        };
                svgtileparameters1_O = {'tileheader':sn,'tiletype':'svg',
                    #'tileid':"tile2",
                    'tileid':svgtileid,
                    #'rowid':"row1",
                    'rowid':"row"+str(rowcnt),
                    #'colid':"col1",
                    'colid':"col"+str(colcnt),
                    'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
                svgtileparameters1_O.update(svgparameters1_O);
                parametersobject_O.append(svgtileparameters1_O);
                tile2datamap_O.update({svgtileid:[iter]});
                dataobject_O.append({"data":data_dict_O[sn],"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
                cnt+=1;
        else:
            cnt = 0;
            svgtileid = "tilesvg"+str(cnt);
            svgid = 'svg'+str(cnt);
            rowcnt = 2;
            colcnt = 1;
            # make the svg object
            svgparameters1_O = {"svgtype":'verticalbarschart2d_01',"svgkeymap":[data1_keymap],
                #'svgid':'svg1',
                'svgid':'svg'+str(cnt),
                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                "svgwidth":500,"svgheight":350,"svgy1axislabel":"intensity (norm)",         
                    };
            svgtileparameters1_O = {'tileheader':'Isotopomer distribution','tiletype':'svg',
                #'tileid':"tile2",
                'tileid':svgtileid,
                #'rowid':"row1",
                #'colid':"col1",
                'rowid':"row"+str(rowcnt),
                'colid':"col"+str(colcnt),
                'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
            svgtileparameters1_O.update(svgparameters1_O);
            parametersobject_O.append(svgparameters1_O);
            tile2datamap_O.update({svgtileid:[0]});
            iter+=1;

        # make the table object
        tableparameters1_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    #"tableheaders":[],
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'tile1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters1_O = {'tileheader':'Isotopomer distribution','tiletype':'table','tileid':"tabletile1",
            'rowid':"row"+str(rowcnt+1),
            'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters1_O.update(tableparameters1_O);
        #dataobject_O.append({"data":data_table_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
        parametersobject_O.append(tabletileparameters1_O);
        tile2datamap_O.update({"tabletile1":[0]})

        #filtermenunsvgtable = ddt_container_filterMenuNSvgTable();
        #filtermenunsvgtable.make_filterMenuNSvgTable(
        #    data_filtermenu=data_O,
        #    data_filtermenu_keys=[data1_keymap],
        #    data_filtermenu_nestkeys=data1_nestkeys,
        #    data_filtermenu_keymap=[data1_keymap],
        #    data_svg_keys=[data1_keymap],
        #    data_svg_nestkeys=data1_nestkeys,
        #    data_svg_keymap=[data1_keymap],
        #    data_table_keys=data1_keys,
        #    data_table_nestkeys=data1_nestkeys,
        #    data_table_keymap=[data1_keymap],
        #    data_svg=data_dict_O,
        #    data_table=data_table_O,
        #    svgtype='verticalbarschart2d_01',
        #    tabletype='responsivetable_01',
        #    svgx1axislabel=None,
        #    svgy1axislabel="intensity (norm)",
        #    single_plot_I=True,
        #    formtile2datamap=[0],
        #    tabletile2datamap=[1],
        #    svgtile2datamap=None,
        #    svgfilters=None,
        #    svgtileheader='Isotopomer distribution',
        #    tablefilters=None,
        #    tableheaders=None
        #    );

        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
 def export_dataStage01RNASequencingGeneExpDiff_js(self,analysis_id_I,p_value_I=0.01,fold_change_log2_I=1.0,data_dir_I='tmp'):
     '''Export data differentially expressed genes as a Volcano Plot
     INPUT:
     OUTPUT:
     '''
     
     # get the analysis information
     experiment_ids,sample_name_abbreviations = [],[];
     experiment_ids,sample_name_abbreviations = self.get_experimentIDAndSampleNameAbbreviation_analysisID_dataStage01RNASequencingAnalysis(analysis_id_I);
     data_O = [];
     for sample_name_abbreviation_cnt_1,sample_name_abbreviation_1 in enumerate(sample_name_abbreviations):
         for sample_name_abbreviation_cnt_2,sample_name_abbreviation_2 in enumerate(sample_name_abbreviations):
             if sample_name_abbreviation_cnt_1 != sample_name_abbreviation_cnt_2:
                 # query geneExpDiff data:
                 geneExpDiff_tmp = [];
                 geneExpDiff_tmp = self.get_rows_experimentIDsAndSampleNameAbbreviations_dataStage01RNASequencingGeneExpDiff(experiment_ids[sample_name_abbreviation_cnt_1],experiment_ids[sample_name_abbreviation_cnt_2],sample_name_abbreviation_1,sample_name_abbreviation_2);
                 geneExpDiff = [];
                 for d in geneExpDiff_tmp:
                     if not 'p_value_negLog10' in d:
                         d['p_value_negLog10']=-log(d['p_value'],10.0);
                     if p_value_I and fold_change_log2_I and d['p_value'] and d['fold_change_log2'] and d['p_value']<=p_value_I and (d['fold_change_log2']>=fold_change_log2_I or d['fold_change_log2']<=-fold_change_log2_I):
                         geneExpDiff.append(d);
                     elif not p_value_I and not fold_change_log2_I and d['p_value'] and d['fold_change_log2']:
                         geneExpDiff.append(d);
                 data_O.extend(geneExpDiff);
     # make the data parameters
     data1_keys = ['experiment_id_1','experiment_id_2','sample_name_abbreviation_1','sample_name_abbreviation_2','gene','fold_change_log2','p_value_negLog10','significant'
                 ];
     data1_nestkeys = ['experiment_id_1'];
     data1_keymap = {'ydata':'p_value_negLog10',
                     'xdata':'fold_change_log2',
                     'serieslabel':'',
                     'featureslabel':'gene'};
     # make the data object
     dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
     # make the tile parameter objects
     formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
     formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
     formtileparameters_O.update(formparameters_O);
     svgparameters_O = {"svgtype":'volcanoplot2d_01',"svgkeymap":[data1_keymap],
                         'svgid':'svg1',
                         "svgmargin":{ 'top': 50, 'right': 50, 'bottom': 50, 'left': 50 },
                         "svgwidth":500,"svgheight":350,
                         "svgx1axislabel":'Fold Change [log2(FC)]',"svgy1axislabel":'Probability [-log10(P)]',
 						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
     svgtileparameters_O = {'tileheader':'Volcano plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
     svgtileparameters_O.update(svgparameters_O);
     tableparameters_O = {"tabletype":'responsivetable_01',
                 'tableid':'table1',
                 "tablefilters":None,
                 "tableclass":"table  table-condensed table-hover",
 			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
     tabletileparameters_O = {'tileheader':'pairWiseTest','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     tabletileparameters_O.update(tableparameters_O);
     parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
     tile2datamap_O = {"filtermenu1":[0],"tile2":[0],"tile3":[0]};
     # dump the data to a json file
     ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
         return data_json_O;
     with open(filename_str,'w') as file:
         file.write(ddtutilities.get_allObjects());
    def export_dataStage02IsotopomerFittedExchangeFluxes_js(self,analysis_id_I = None,
                        simulation_ids_I = [],
                        bullet_chart_I = True,
                        data_dir_I="tmp"):
        '''Plot the flux precision for a given set of simulations and a given set of reactions
        Input:
        analysis_id_I = string, analysis id
        Optional Input:
        simulation_ids_I = [] of strings, simulation_ids in a specific order
        bullet_chart_I = True: show the flux estimation +/- StDev
                         False: show the 95% confidence invervals and flux estimation +/- StDev
        '''
        MFAmethods = MFA_methods();
        #Input:
        # analysis_id_I or
        # simulation_ids_I

        if simulation_ids_I:
            simulation_ids = simulation_ids_I;
        else:
            simulation_ids = [];
            simulation_ids = self.get_simulationID_analysisID_dataStage02IsotopomerAnalysis(analysis_id_I);
        data_O =[]; 
        for simulation_id in simulation_ids:
            # get the flux information for each simulation
            flux_data = [];
            flux_data = self.get_rows_simulationID_dataStage02IsotopomerfittedExchangeFluxes(simulation_id);
            #min_flux,max_flux = None,None;
            #min_flux,max_flux = self.get_fluxMinAndMax_simulationID_dataStage02IsotopomerfittedExchangeFluxes(simulation_id)
            for i,row in enumerate(flux_data):
                observable = MFAmethods.check_observableExchangeFlux(row['flux'],row['flux_lb'],row['flux_ub']);
                if not row['flux'] is None:
                    row['simulation_dateAndTime'] = self.convert_datetime2string(row['simulation_dateAndTime']);
                    #row['flux_units'] = row['flux_units'].replace('*','x');
                    row['flux_lb_stdev'] = row['flux'] - row['flux_stdev'];
                    row['flux_ub_stdev'] = row['flux'] + row['flux_stdev'];
                    row['flux_mean'] = numpy.mean([row['flux_lb'],row['flux_ub']]);
                    if observable: row['observable'] = 'Yes';
                    else: row['observable'] = 'No';
                    data_O.append(row);
                #if not row['flux'] is None and observable:
                #    row['simulation_dateAndTime'] = self.convert_datetime2string(row['simulation_dateAndTime']);
                #    row['flux_units'] = row['flux_units'].replace('*','x');
                #    row['flux_lb_stdev'] = row['flux'] - row['flux_stdev'];
                #    row['flux_ub_stdev'] = row['flux'] + row['flux_stdev'];
                #    row['flux_mean'] = numpy.mean([row['flux_lb'],row['flux_ub']]);
                #    data_O.append(row);
                #elif not row['flux'] is None and not observable: 
                #    row['simulation_dateAndTime'] = self.convert_datetime2string(row['simulation_dateAndTime']);
                #    row['flux_units'] = row['flux_units'].replace('*','x');
                #    row['flux_lb'] = None;
                #    row['flux_ub'] = None;
                #    row['flux_mean'] = None;
                #    data_O.append(row);
                #elif row['flux']==0.0 and observable:
                #    row['simulation_dateAndTime'] = self.convert_datetime2string(row['simulation_dateAndTime']);
                #    row['flux_units'] = row['flux_units'].replace('*','x');
                #    row['flux_lb_stdev'] = 0.0;
                #    row['flux_ub_stdev'] = 0.0;
                #    row['flux_mean'] = numpy.mean([row['flux_lb'],row['flux_ub']]);
                #    data_O.append(row);
                #elif row['flux']==0.0 and not observable:
                #    row['simulation_dateAndTime'] = self.convert_datetime2string(row['simulation_dateAndTime']);
                #    row['flux_units'] = row['flux_units'].replace('*','x');
                #    row['flux_lb'] = None;
                #    row['flux_ub'] = None;
                #    #row['flux_mean'] = None;
                #    row['flux_lb_stdev'] = None;
                #    row['flux_ub_stdev'] = None;
                #    row['flux']=None;
                #    data_O.append(row);
                elif row['flux']==0.0:
                    row['simulation_dateAndTime'] = self.convert_datetime2string(row['simulation_dateAndTime']);
                    row['flux_units'] = row['flux_units'].replace('*','x');
                    row['flux_lb_stdev'] = 0.0;
                    row['flux_ub_stdev'] = 0.0;
                    row['flux_mean'] = numpy.mean([row['flux_lb'],row['flux_ub']]);
                    if observable: row['observable'] = 'Yes';
                    else: row['observable'] = 'No';
                    data_O.append(row);
        # dump chart parameters to a js files
        data1_keys = ['simulation_id','rxn_id','simulation_dateAndTime','flux_units','observable'
                    ];
        data1_nestkeys = ['rxn_id'];
        if bullet_chart_I:
            data1_keymap = {'xdata':'rxn_id',
                        'ydatamean':'flux',
                        'ydatalb':'flux_lb_stdev',
                        'ydataub':'flux_ub_stdev',
                        'serieslabel':'simulation_id',
                        'featureslabel':'rxn_id'};
        else:
            data1_keymap = {'xdata':'rxn_id',
                        #'ydata':'flux',
                        'ydatamean':'flux_mean',
                        'ydatalb':'flux_lb',
                        'ydataub':'flux_ub',
                        #'ydatamin':'min',
                        #'ydatamax':'max',
                        'ydataiq1':'flux_lb_stdev',
                        'ydataiq3':'flux_ub_stdev',
                        'ydatamedian':'flux',
                        'serieslabel':'simulation_id',
                        'featureslabel':'rxn_id'};
        # make the data object
        dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        svgparameters_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data1_keymap,data1_keymap],
                            'svgid':'svg1',
                            "svgmargin":{ 'top': 50, 'right': 350, 'bottom': 50, 'left': 50 },
                            "svgwidth":750,"svgheight":350,
                            "svgx1axislabel":"rxn_id","svgy1axislabel":"flux",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_O = {'tileheader':'Flux precision','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        svgtileparameters_O.update(svgparameters_O);
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'Flux precision','tiletype':'table','tileid':"tile3",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
        tile2datamap_O = {"filtermenu1":[0],"tile2":[0],"tile3":[0]};

        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage02IsotopomerFluxMap_js(self,analysis_id_I,simulation_id_I = None,data_dir_I="tmp"):
        '''Export flux map for viewing'''
        
        MFAmethods = MFA_methods();
        # Get the simulation information
        if simulation_id_I:
            simulation_id = simulation_id_I;
        else:
            simulation_ids = [];
            simulation_ids = self.get_simulationID_analysisID_dataStage02IsotopomerAnalysis(analysis_id_I);
        if not simulation_ids:
            print('No simulation found for the analysis_id ' + analysis_id_I);
        elif len(simulation_ids)>1:
            print('More than 1 simulation found for the analysis_id ' + analysis_id_I);
            simulation_id_I = simulation_ids[0];
        else:
            simulation_id_I = simulation_ids[0];
        # Get the flux information
        flux = [];
        flux_tmp = [];
        #flux = self.get_rowsEscherFluxList_simulationID_dataStage02IsotopomerfittedExchangeFluxes(simulation_id_I);
        flux_tmp = self.get_rows_simulationID_dataStage02IsotopomerfittedExchangeFluxes(simulation_id_I);
        for i,row in enumerate(flux_tmp):
            observable = MFAmethods.check_observableExchangeFlux(row['flux'],row['flux_lb'],row['flux_ub']);
            if not row['flux'] is None and row['flux']!=0.0 and numpy.abs(row['flux']) < 10.0:
                flux_tmp[i]['simulation_dateAndTime'] = self.convert_datetime2string(row['simulation_dateAndTime']);
                flux_tmp[i]['flux_units'] = self.remove_jsRegularExpressions(row['flux_units']);
                if observable: flux_tmp[i]['observable'] = 'Yes';
                else: flux_tmp[i]['observable'] = 'No';
                flux.append(flux_tmp[i]);
            elif row['flux']==0.0 and numpy.abs(numpy.mean([row['flux_lb'],row['flux_ub']]))<10.0:
                flux_tmp[i]['simulation_dateAndTime'] = self.convert_datetime2string(row['simulation_dateAndTime']);
                flux_tmp[i]['flux_units'] = self.remove_jsRegularExpressions(row['flux_units']);
                #flux_tmp[i]['flux'] = numpy.mean([row['flux_lb'],row['flux_ub']]);
                if observable: flux_tmp[i]['observable'] = 'Yes';
                else: flux_tmp[i]['observable'] = 'No';
                flux.append(flux_tmp[i]);

        # Get the map information
        map = [];
        map = self.get_rows_modelID_modelsEschermaps('iJO1366');
        # dump chart parameters to a js files
        data1_keys = ['simulation_id','rxn_id','simulation_dateAndTime','flux_units','observable'
                    ];
        data1_nestkeys = ['simulation_id'];
        data1_keymap = {'values':'flux','key':'rxn_id'};
        data2_keys = ['model_id','eschermap_id'
                    ];
        data2_nestkeys = ['model_id'];
        data2_keymap = {'data':'eschermap_json'};
        # make the data object
        dataobject_O = [{"data":flux,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":map,"datakeys":data2_keys,"datanestkeys":data2_nestkeys}];
        # make the tile parameter objects
        formtileparameters1_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters1_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters1_O.update(formparameters1_O);
        formtileparameters2_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu2",'rowid':"row1",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters2_O = {'htmlid':'filtermenuform2',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit2','text':'submit'},"formresetbuttonidtext":{'id':'reset2','text':'reset'},"formupdatebuttonidtext":{'id':'update2','text':'update'}};
        formtileparameters2_O.update(formparameters2_O);
        htmlparameters_O = {"htmlkeymap":[data1_keymap,data2_keymap],
                        'htmltype':'escher_01','htmlid':'html1',
                        'escherdataindex':{"reactiondata":0,"mapdata":1},
                        'escherembeddedcss':None,
                        'escheroptions':None};
        htmltileparameters_O = {'tileheader':'Escher map','tiletype':'html','tileid':"tile1",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        htmltileparameters_O.update(htmlparameters_O);
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'Flux precision','tiletype':'table','tileid':"tile2",'rowid':"row3",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O = [formtileparameters1_O,formtileparameters2_O,htmltileparameters_O,tabletileparameters_O];
        tile2datamap_O = {"filtermenu1":[0],"filtermenu2":[1],"tile1":[0,1],"tile2":[0]};
        filtermenuobject_O = [{"filtermenuid":"filtermenu1","filtermenuhtmlid":"filtermenuform1",
                "filtermenusubmitbuttonid":"submit1","filtermenuresetbuttonid":"reset1",
                "filtermenuupdatebuttonid":"update1"},{"filtermenuid":"filtermenu2","filtermenuhtmlid":"filtermenuform2",
                "filtermenusubmitbuttonid":"submit2","filtermenuresetbuttonid":"reset2",
                "filtermenuupdatebuttonid":"update2"}];
        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
 def export_dataStage01PhysiologyRatesAverages_js_v01(self,analysis_id_I,data_dir_I="tmp"):
     """Export data_stage01_physiology_ratesAverages to js file"""
     # get the analysis information
     experiment_ids,sample_name_abbreviations = [],[];
     experiment_ids,sample_name_abbreviations = self.get_experimentIDAndSampleName_analysisID_dataStage01PhysiologyAnalysis(analysis_id_I);
     data_O = [];
     for sna_cnt,sna in enumerate(sample_name_abbreviations):
         data_tmp = [];
         data_tmp = self.get_rows_experimentIDAndSampleNameAbbreviation_dataStage01PhysiologyRatesAverages(experiment_ids[sna_cnt],sna);
         if data_tmp: data_O.extend(data_tmp);
     ## remove js regular expressions
     #for i,d in enumerate(data_O):
     #    data_O[i]['rate_units'] = self.remove_jsRegularExpressions(d['rate_units']);
     # get metabolite ids:
     met_ids_all = [];
     for d in data_O:
         met_ids_all.append(d['met_id']);
     met_ids = list(set(met_ids_all));
     biomass_met_ids = ['biomass','yield_ss'];
     uptakesecretion_met_ids = [x for x in met_ids if not x in biomass_met_ids];
     # visualization parameters
     data1_keys = ['experiment_id','sample_name_abbreviation', 'met_id','rate_units'];
     data1_nestkeys = ['met_id'];
     data1_keymap = {'xdata':'met_id','ydata':'rate_average',
             'serieslabel':'sample_name_abbreviation','featureslabel':'met_id',
             'ydatalb':'rate_lb','ydataub':'rate_ub'};
     # make the data object
     dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
     # make the tile parameter objects
     svgparameters1_O = {"svgtype":'verticalbarschart2d_01',"svgkeymap":[data1_keymap],
                         'svgid':'svg1',
                          "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                 "svgwidth":500,"svgheight":350,"svgy1axislabel":"rate (mmol*gDCW-1*hr-1)",
               "svgfilters":{'met_id':uptakesecretion_met_ids}
             };
     svgtileparameters1_O = {'tileheader':'Uptake/secretion rates','tiletype':'svg','tileid':"tile1",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     svgtileparameters1_O.update(svgparameters1_O);
     svgparameters2_O = {"svgtype":'verticalbarschart2d_01',"svgkeymap":[data1_keymap],
                         'svgid':'svg2',
               "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
               "svgwidth":500,"svgheight":350,
               "svgy1axislabel":"rate (hr-1)",
               #"svgy1axislabel":"rate (hr-1) or yield (gDCW*mmol of C-source)",
               "svgfilters":{'met_id':biomass_met_ids}
             };
     svgtileparameters2_O = {'tileheader':'Growth rate','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     svgtileparameters2_O.update(svgparameters2_O);
     tableparameters1_O = {"tabletype":'responsivetable_01',
                 'tableid':'table1',
                 "tablefilters":None,
                 "tableheaders":['experiment_id','sample_name_abbreviation','met_id','rate_average','rate_var','rate_lb','rate_ub','rate_units','n','comment_','used_'],
                 "tableclass":"table  table-condensed table-hover",
 			    'tableformtileid':'tile1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
     tabletileparameters1_O = {'tileheader':'Uptake/secretion rates','tiletype':'table','tileid':"tile3",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     tabletileparameters1_O.update(tableparameters1_O);
     tableparameters2_O = {"tabletype":'responsivetable_01',
                 'tableid':'table2',
                 "tablefilters":None,
                 "tableheaders":['experiment_id','sample_name_abbreviation','met_id','rate_average','rate_var','rate_lb','rate_ub','rate_units','n','comment_','used_'],
                 "tableclass":"table  table-condensed table-hover",
 			    'tableformtileid':'tile1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
     tabletileparameters2_O = {'tileheader':'Growth rates','tiletype':'table','tileid':"tile4",'rowid':"row1",'colid':"col1",
         'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
     tabletileparameters2_O.update(tableparameters2_O);
     parametersobject_O = [svgtileparameters1_O,svgtileparameters2_O,tabletileparameters1_O,tabletileparameters2_O];
     tile2datamap_O = {"tile1":[0],"tile2":[1],"tile3":[0],"tile4":[1]};
     filtermenuobject_O = None;
     # dump the data to a json file
     ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
     if data_dir_I=='tmp':
         filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
     elif data_dir_I=='data_json':
         data_json_O = ddtutilities.get_allObjects_js();
         return data_json_O;
     with open(filename_str,'w') as file:
         file.write(ddtutilities.get_allObjects());  
    def export_quantitationMethods_js(self,analysis_id_I,data_dir_I='tmp'):
        '''Export the quantitation and calibrators to ddt'''
        #get the calibrator data
        data_1 = [];
        data_2 = [];
        data_1a = [];

        #query all the data
        data_all = self.getRowsJoin_analysisID_dataStage01QuantificationMQResultsTable_limsQuantitationMethod(analysis_id_I)

        #reorganize into a dictionary of (QMethods,component_names)
        data_dict = {};
        for d in data_all:
            unique = (d['quantitation_method_id'],d['component_name']);
            if not unique in data_dict.keys():
                data_dict[unique] = [];
            data_dict[unique].append(d);

        #split and modify the data
        for QMethod_id,rows in data_dict.items():
            concentrations = []
            ratios = [];
            sample_names = [];
            for row in rows:
                if row and not row is None and not row['concentration_ratio'] is None:
                    if row['use_area']: row['ratio'] = row['area_ratio'];
                    else: row['ratio'] = row['height_ratio'];
                    row['quantitation_method_id']=rows[0]['quantitation_method_id'];
                    data_1.append(row);
                    concentrations.append(row['concentration_ratio']);
                    ratios.append(row['ratio']);
                    sample_names.append(row['sample_name']);
            if not concentrations: continue;

            # get the quant method statistics
            data_2.append(row);

            # generate the line of best fit
            min_ratio = min(ratios);
            max_ratio = max(ratios);
            index_min = [cnt for cnt,x in enumerate(ratios) if x == min_ratio][0];
            index_max = [cnt for cnt,x in enumerate(ratios) if x == max_ratio][0];
            conc_min = min(concentrations);
            conc_max = max(concentrations);
            sample_name_min = sample_names[index_min];
            sample_name_max = sample_names[index_max];
            data_1a.append({'concentration_ratio':rows[0]['lloq'],
                    'ratio':min_ratio,
                    'component_name':rows[0]['component_name'],
                    'sample_name':sample_name_min,
                    'quantitation_method_id':rows[0]['quantitation_method_id']});
            data_1a.append({'concentration_ratio':rows[0]['uloq'],
                    'ratio':max_ratio,
                    'component_name':rows[0]['component_name'],
                    'sample_name':sample_name_max,
                    'quantitation_method_id':rows[0]['quantitation_method_id']});
                
        # dump chart parameters to a js files
        data1_keys = [
                    'quantitation_method_id',
                    'concentration_ratio',
                    'sample_name',
                    'component_name',
                    'ratio',
                    ];
        data1_nestkeys = ['component_name'];
        data1_keymap = {'xdata':'concentration_ratio',
                        'ydata':'ratio',
                        'serieslabel':'component_name',
                        'featureslabel':'sample_name'};
        data2_keys = ['quantitation_method_id',
                    'q1_mass',
                    'q3_mass',
                    'met_id',
                    'component_name',
                    'is_name',
                    'fit',
                    'weighting',
                    'intercept',
                    'slope',
                    'correlation',
                    'use_area',
                    'lloq',
                    'uloq',
                    'points',
                    ];
        data2_nestkeys = ['component_name'];
        data2_keymap = {'xdata':'concentration_ratio',
                        'ydata':'ratio',
                        'serieslabel':'component_name',
                        'featureslabel':None};
        parameters = {"chart1margin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                    "chart1width":500,"chart1height":350,
                  "chart1title":"Metric Plot", "chart1x1axislabel":"sample_name","chart1y1axislabel":"measurement"}
        # make the data object
        dataobject_O = [{"data":data_1,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_1a,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_2,"datakeys":data2_keys,"datanestkeys":data2_nestkeys}];
        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        formparameters_O = {'htmlid':'filtermenuform1','htmltype':'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        svgparameters_O = {"svgtype":'scatterlineplot2d_01',"svgkeymap":[data1_keymap,data1_keymap],
                            'svgid':'svg1',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":500,"svgheight":350,
                            "svgx1axislabel":"concentration_ratio","svgy1axislabel":"measurement_ratio",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_O = {'tileheader':'Regression','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
        svgtileparameters_O.update(svgparameters_O);
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'Regression Statistics','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
        tile2datamap_O = {"filtermenu1":[0],"tile2":[0,1],"tile3":[2]};
        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01QuantificationPhysiologicalRatios_js(self,experiment_id_I,sample_name_abbreviations_I=[],ratio_ids_I=[],
                                                               data_dir_I = 'tmp'):
        '''Export the data from data_stage01_phyisiogicalRatios for visualization with DDT
        NOTES:
        Broken...
        Update to use box and whiskers with points for individual replicates
        Update to use ddt_python interface

        INPUT:
        experiment_id_I
        sample_name_abbreviations_I
        ratio_ids_I
        data_dir_I

        OUTPUT:

        '''
        print('Generating scatterLinePlot for physiologicalRatios')
        data_replicates = [];
        data_averages = [];
        data_numAndDen = [];
        # get time points
        time_points = [];
        time_points = self.get_timePoint_experimentID_dataStage01PhysiologicalRatiosReplicates(experiment_id_I);
        for tp in time_points:
            print('Generating scatterLinePlot for physiologicalRatios for time_point ' + tp);
            # get physiological ratio_ids
            ratios = {};
            ratios = self.get_ratioIDs_experimentIDAndTimePoint_dataStage01PhysiologicalRatiosReplicates(experiment_id_I,tp);
            for k,v in ratios.items():
                if ratio_ids_I: 
                    if not k in ratio_ids_I:
                        continue;
                print('Generating scatterLinePlot for physiologicalRatios for ratio ' + k);
                # get sample_names
                if sample_name_abbreviations_I:
                    sample_name_abbreviations = sample_name_abbreviations_I;
                else:
                    sample_name_abbreviations = [];
                    sample_name_abbreviations = self.get_sampleNameAbbreviations_experimentIDAndTimePointAndRatioID_dataStage01PhysiologicalRatiosAverages(experiment_id_I,tp,k);
                ratios_num = [];
                ratios_den = [];
                for sna_cnt,sna in enumerate(sample_name_abbreviations):
                    print('Generating scatterLinePlot for physiologicalRatios for sample name abbreviation ' + sna);
                    # get the data 
                    data = {};
                    data = self.get_data_experimentIDAndTimePointAndRatioIDAndSampleNameAbbreviation_dataStage01PhysiologicalRatiosAverages(experiment_id_I,tp,k,sna)
                    if not data: continue;
                    data_averages.append(data);
                    # get the replicates
                    ratio_values = [];
                    ratio_values = self.get_rows_experimentIDAndSampleNameAbbreviationAndTimePointAndRatioID_dataStage01PhysiologicalRatiosReplicates(experiment_id_I,sna,tp,k);
                    for ratio in ratio_values:
                        ratio['sample_name_abbreviation']=sna;
                    data_replicates.extend(ratio_values);
                    ratio_values = [];
                    ratio_values = self.get_rows_experimentIDAndSampleNameAbbreviationAndTimePointAndRatioID_dataStage01PhysiologicalRatiosReplicates(experiment_id_I,sna,tp,k+'_numerator');
                    for ratio in ratio_values:
                        ratio['sample_name_abbreviation']=sna;
                    data_replicates.extend(ratio_values);
                    ratio_values = [];
                    ratio_values = self.get_rows_experimentIDAndSampleNameAbbreviationAndTimePointAndRatioID_dataStage01PhysiologicalRatiosReplicates(experiment_id_I,sna,tp,k+'_denominator');
                    for ratio in ratio_values:
                        ratio['sample_name_abbreviation']=sna;
                    data_replicates.extend(ratio_values);
                    # get ratios_numerator
                    ratio_num = None;
                    ratio_num = self.get_data_experimentIDAndTimePointAndRatioIDAndSampleNameAbbreviation_dataStage01PhysiologicalRatiosAverages(experiment_id_I,tp,k+'_numerator',sna)
                    if not ratio_num: continue;
                    # get ratios_denominator
                    ratio_den = None;
                    ratio_den = self.get_data_experimentIDAndTimePointAndRatioIDAndSampleNameAbbreviation_dataStage01PhysiologicalRatiosAverages(experiment_id_I,tp,k+'_denominator',sna)
                    if not ratio_den: continue;
                    # modify
                    ratio = {};
                    if ratio_num['sample_name_abbreviation']==ratio_den['sample_name_abbreviation']:
                        ratio = {'experiment_id':ratio_num['experiment_id'],
                                'sample_name_abbreviation':ratio_num['sample_name_abbreviation'],
                                'time_point':ratio_num['time_point'],
                                'physiologicalratio_name':ratio_num['physiologicalratio_name'],
                                'physiologicalratio_description':ratio_num['physiologicalratio_description']}
                        ratio['physiologicalratio_id'] = ratio_num['physiologicalratio_id'].replace('_numerator','');
                        ratio['physiologicalratio_value_numerator'] = ratio_num['physiologicalratio_value_ave'];
                        ratio['physiologicalratio_value_denominator'] = ratio_den['physiologicalratio_value_ave'];
                    else:
                        print('physiologicalratio sample_name_shorts do not match');
                    data_numAndDen.append(ratio);
        # dump chart parameters to a js files
        data1_keys = ['experiment_id',
                      'sample_name_abbreviation',
                      'sample_name_short',
                      'time_point',
                      'physiologicalratio_id',
                      'physiologicalratio_name',
                      'physiologicalratio_description',
                    ];
        data1_nestkeys = ['physiologicalratio_id'];
        data1_keymap = {'xdata':'physiologicalratio_id',
                        'ydata':'physiologicalratio_value',
                        #'ydatalb':'physiologicalratio_value_lb',
                        #'ydataub':'physiologicalratio_value_ub',
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_short',
                        'featureslabel':'physiologicalratio_id'};
        data2_keys = ['experiment_id',
                      'sample_name_abbreviation',
                      'time_point',
                      'physiologicalratio_id',
                      'physiologicalratio_name',
                      'physiologicalratio_description',
                      'physiologicalratio_cv'
                    ];
        data2_nestkeys = ['physiologicalratio_id'];
        data2_keymap = {'xdata':'physiologicalratio_id',
                        'ydatamean':'physiologicalratio_value_ave',
                        'ydatalb':'physiologicalratio_value_lb',
                        'ydataub':'physiologicalratio_value_ub',
                        #'ydatamin':None,
                        #'ydatamax':None,
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'physiologicalratio_id'};
        data3_keys = [
                    'experiment_id',
                      'sample_name_abbreviation',
                      'time_point',
                      'physiologicalratio_id',
                      'physiologicalratio_name',
                      'physiologicalratio_description'
                    ];
        data3_nestkeys = ['physiologicalratio_id'];
        data3_keymap = {'xdata':'physiologicalratio_value_denominator',
                        'ydata':'physiologicalratio_value_numerator',
                        'serieslabel':'physiologicalratio_id',
                        'featureslabel':'sample_name_abbreviation'};
        # make the data object
        dataobject_O = [{"data":data_replicates,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_averages,"datakeys":data2_keys,"datanestkeys":data2_nestkeys},
                        {"data":data_numAndDen,"datakeys":data3_keys,"datanestkeys":data3_nestkeys}];
        # make the tile parameter objects for the replicates and averages
        formtileparameters_replicates_O = {'tileheader':'Filter menu replicates','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters_replicates_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_replicates_O.update(formparameters_replicates_O);
        formtileparameters_averages_O = {'tileheader':'Filter menu averages','tiletype':'html','tileid':"filtermenu2",'rowid':"row1",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters_averages_O = {'htmlid':'filtermenuform2',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit2','text':'submit'},"formresetbuttonidtext":{'id':'reset2','text':'reset'},"formupdatebuttonidtext":{'id':'update2','text':'update'}};
        formtileparameters_averages_O.update(formparameters_averages_O);
        # make the svg objects for the replicates data
        svgparameters_replicates_O = {"svgtype":'boxandwhiskersplot2d_01',"svgkeymap":[data1_keymap],
                            'svgid':'svg1',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":500,"svgheight":350,
                            "svgx1axislabel":"physiologicalratio_id","svgy1axislabel":"value",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_replicates_O = {'tileheader':'Replicates','tiletype':'svg','tileid':"tile1",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        svgtileparameters_replicates_O.update(svgparameters_replicates_O);
        # make the svg objects for the box and whiskers data
        svgparameters_boxAndWhiskers_O = {"svgtype":'boxandwhiskersplot2d_01',"svgkeymap":[data2_keymap],
                            'svgid':'svg2',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":350,"svgheight":350,
                            "svgx1axislabel":"physiologicalratio_id","svgy1axislabel":"value",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_boxAndWhiskers_O = {'tileheader':'Ratio','tiletype':'svg','tileid':"tile2",'rowid':"row3",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        svgtileparameters_boxAndWhiskers_O.update(svgparameters_boxAndWhiskers_O);
        # make the svg objects for the scatter line plot data
        svgparameters_scatterLinePlot_O = {"svgtype":'scatterlineplot2d_01',"svgkeymap":[data3_keymap,data3_keymap],
                            'svgid':'svg3',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":350,"svgheight":350,
                            "svgx1axislabel":"physiologicalratio_denominator","svgy1axislabel":"physiologicalratio_numerator",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_scatterLinePlot_O = {'tileheader':'Ratio numerator vs. denominator','tiletype':'svg','tileid':"tile3",'rowid':"row4",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        svgtileparameters_scatterLinePlot_O.update(svgparameters_scatterLinePlot_O);
        # make the tables for the replicates and averages data
        tableparameters_replicates_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_replicates_O = {'tileheader':'replicates data','tiletype':'table','tileid':"tile7",'rowid':"row5",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_replicates_O.update(tableparameters_replicates_O);
        tableparameters_averages_O = {"tabletype":'responsivetable_01',
                    'tableid':'table2',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu2','tableresetbuttonid':'reset2','tablesubmitbuttonid':'submit2'};
        tabletileparameters_averages_O = {'tileheader':'averages data','tiletype':'table','tileid':"tile8",'rowid':"row6",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_averages_O.update(tableparameters_averages_O);
        parametersobject_O = [formtileparameters_replicates_O,
                              formtileparameters_averages_O,
                              svgtileparameters_replicates_O,
                              svgtileparameters_boxAndWhiskers_O,
                              svgtileparameters_scatterLinePlot_O,
                              tabletileparameters_replicates_O,
                              tabletileparameters_averages_O];
        tile2datamap_O = {"filtermenu1":[0],"filtermenu2":[1],
                          "tile1":[0],"tile2":[1],"tile3":[2,2],
                          "tile7":[0],"tile8":[1]};
        filtermenuobject_O = [
            {"filtermenuid":"filtermenu1","filtermenuhtmlid":"filtermenuform1",
                "filtermenusubmitbuttonid":"submit1","filtermenuresetbuttonid":"reset1",
                "filtermenuupdatebuttonid":"update1"},
                {"filtermenuid":"filtermenu2","filtermenuhtmlid":"filtermenuform2",
                "filtermenusubmitbuttonid":"submit2","filtermenuresetbuttonid":"reset2",
                "filtermenuupdatebuttonid":"update2"}
                              ];
        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01NormalizedAndAverages_checkCVAndExtracelluar_js(self,experiment_id_I,sample_name_abbreviations_I=[],sample_names_I=[],component_names_I=[],
                                                   cv_threshold_I=40,extracellular_threshold_I=80,
                                                   data_dir_I='tmp'):
        '''export data_stage01_quantification_normalized and averages for visualization with ddt'''

        calc = calculate_interface();
        
        print('export_dataStage01Normalized_js...')
        data_norm_broth = [];
        data_norm_filtrate = [];
        data_norm_combined = [];
        data_ave = [];
        # get sample_name_abbreviations
        if sample_name_abbreviations_I:
            sample_name_abbreviations = sample_name_abbreviations_I
        else:
            sample_name_abbreviations = [];
            sample_name_abbreviations = self.get_sampleNameAbbreviations_experimentID_dataStage01Normalized(experiment_id_I);
        # create database table
        for sna in sample_name_abbreviations:
            print('exporting sample_name_abbreviation ' + sna);
            # get component names
            if component_names_I:
                component_names = component_names_I
            else:
                component_names = [];
                component_names = self.get_componentsNames_experimentIDAndSampleNameAbbreviation_dataStage01Normalized(experiment_id_I,sna);
            for cn in component_names:
                print('exporting component_name ' + cn);
                component_group_name = self.get_componentGroupName_experimentIDAndComponentName_dataStage01Normalized(experiment_id_I,cn);
                # get time points
                time_points = self.get_timePoint_experimentIDAndSampleNameAbbreviation_dataStage01Normalized(experiment_id_I,sna);
                for tp in time_points:
                    print('exporting time_point ' + tp);
                    # get the averages and %CV samples
                    row = {};
                    #row = self.get_row_experimentIDAndSampleNameAbbreviationAndTimePointAndComponentName_dataStage01Averages(experiment_id_I,sna,tp,cn);
                    row = self.get_row_experimentIDAndSampleNameAbbreviationAndTimePointAndComponentNameAndCalculatedConcentrationCVAndExtracellularPercent_dataStage01Averages(experiment_id_I,
                                                                        sna,tp,cn,
                                                                        cv_threshold_I=cv_threshold_I,
                                                                        extracellular_threshold_I=extracellular_threshold_I);
                    if not row: continue;
                    stdev = calc.convert_cv2StDev(row['calculated_concentration_filtrate_average'],row['calculated_concentration_filtrate_cv']);
                    row['calculated_concentration_filtrate_lb'] = row['calculated_concentration_filtrate_average']-stdev;
                    row['calculated_concentration_filtrate_ub'] = row['calculated_concentration_filtrate_average']+stdev;
                    stdev = calc.convert_cv2StDev(row['calculated_concentration_broth_average'],row['calculated_concentration_broth_cv']);
                    row['calculated_concentration_broth_lb'] = row['calculated_concentration_broth_average']-stdev;
                    row['calculated_concentration_broth_ub'] = row['calculated_concentration_broth_average']+stdev;
                    stdev = calc.convert_cv2StDev(row['calculated_concentration_average'],row['calculated_concentration_cv']);
                    row['calculated_concentration_lb'] = row['calculated_concentration_average']-stdev;
                    row['calculated_concentration_ub'] = row['calculated_concentration_average']+stdev;
                    data_ave.append(row);
                    # get filtrate sample names
                    sample_names = [];
                    sample_description = 'Filtrate';
                    sample_names = self.get_sampleNames_experimentIDAndSampleNameAbbreviationAndSampleDescriptionAndComponentNameAndTimePoint_dataStage01Normalized(experiment_id_I,sna,sample_description,cn,tp);
                    if sample_names_I: # screen out sample names that are not in the input
                        sample_names = [x for x in sample_names if x in sample_names_I];
                    for sn in sample_names:
                        # get the row
                        row = None;
                        row = self.get_row_sampleNameAndComponentName_dataStage01Normalized(sn,cn);
                        if not(row): continue;
                        row['sample_name_abbreviation'] = sna;
                        data_norm_filtrate.append(row);
                        data_norm_combined.append(row);
                    # get filtrate sample names
                    sample_names = [];
                    sample_description = 'Broth';
                    sample_names = self.get_sampleNames_experimentIDAndSampleNameAbbreviationAndSampleDescriptionAndComponentNameAndTimePoint_dataStage01Normalized(experiment_id_I,sna,sample_description,cn,tp);
                    if sample_names_I: # screen out sample names that are not in the input
                        sample_names = [x for x in sample_names if x in sample_names_I];
                    for sn in sample_names:
                        # get the row
                        row = None;
                        row = self.get_row_sampleNameAndComponentName_dataStage01Normalized(sn,cn);
                        if not(row): continue;
                        row['sample_name_abbreviation'] = sna;
                        data_norm_broth.append(row);
                        data_norm_combined.append(row);
        # dump chart parameters to a js files
        data1_keys = ['experiment_id',
                      'sample_name',
                      'sample_id',
                      'sample_name_abbreviation',
                      'component_group_name',
                      'component_name',
                      'calculated_concentration_units'
                    ];
        data1_nestkeys = ['component_name'];
        data1_keymap = {'xdata':'component_name',
                        'ydatamean':'calculated_concentration',
                        #'ydatalb':'peakInfo_lb',
                        #'ydataub':'peakInfo_ub',
                        #'ydatamin':None,
                        #'ydatamax':None,
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name',
                        'featureslabel':'component_name'};
        data2_keys = ['experiment_id',
                      'sample_name_abbreviation',
                      'time_point',
                      'component_group_name',
                      'component_name',
                      'calculated_concentration_units',
                      'extracellular_percent',
                      'calculated_concentration_broth_cv'
                    ];
        data2_nestkeys = ['component_name'];
        data2_keymap = {'xdata':'component_name',
                        'ydatamean':'calculated_concentration_broth_average',
                        'ydatalb':'calculated_concentration_broth_lb',
                        'ydataub':'calculated_concentration_broth_ub',
                        #'ydatamin':None,
                        #'ydatamax':None,
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'component_name'};
        data3_keys = ['experiment_id',
                      'sample_name_abbreviation',
                      'time_point',
                      'component_group_name',
                      'component_name',
                      'calculated_concentration_units',
                      'extracellular_percent',
                      'calculated_concentration_filtrate_cv'
                    ];
        data3_nestkeys = ['component_name'];
        data3_keymap = {'xdata':'component_name',
                        'ydatamean':'calculated_concentration_filtrate_average',
                        'ydatalb':'calculated_concentration_filtrate_lb',
                        'ydataub':'calculated_concentration_filtrate_ub',
                        #'ydatamin':None,
                        #'ydatamax':None,
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'component_name'};
        data4_keys = ['experiment_id',
                      'sample_name_abbreviation',
                      'time_point',
                      'component_group_name',
                      'component_name',
                      'calculated_concentration_units',
                      'extracellular_percent',
                      'calculated_concentration_cv'
                    ];
        data4_nestkeys = ['component_name'];
        data4_keymap = {'xdata':'component_name',
                        'ydatamean':'calculated_concentration_average',
                        'ydatalb':'calculated_concentration_lb',
                        'ydataub':'calculated_concentration_ub',
                        #'ydatamin':None,
                        #'ydatamax':None,
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'sample_name_abbreviation',
                        'featureslabel':'component_name'};
        # make the data object
        dataobject_O = [{"data":data_norm_broth,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_norm_filtrate,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_norm_combined,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":data_ave,"datakeys":data2_keys,"datanestkeys":data2_nestkeys},
                        {"data":data_ave,"datakeys":data3_keys,"datanestkeys":data3_nestkeys},
                        {"data":data_ave,"datakeys":data4_keys,"datanestkeys":data4_nestkeys}];
        # make the tile parameter objects for the normalized and averages
        formtileparameters_normalized_O = {'tileheader':'Filter menu normalized','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters_normalized_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_normalized_O.update(formparameters_normalized_O);
        formtileparameters_averages_O = {'tileheader':'Filter menu averages','tiletype':'html','tileid':"filtermenu2",'rowid':"row1",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-6"};
        formparameters_averages_O = {'htmlid':'filtermenuform2',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit2','text':'submit'},"formresetbuttonidtext":{'id':'reset2','text':'reset'},"formupdatebuttonidtext":{'id':'update2','text':'update'}};
        formtileparameters_averages_O.update(formparameters_averages_O);
        # make the svg objects for the normalized data
        svgparameters_broth_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data1_keymap],
                            'svgid':'svg1',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_broth_O = {'tileheader':'Broth data','tiletype':'svg','tileid':"tile1",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        svgtileparameters_broth_O.update(svgparameters_broth_O);
        svgparameters_filtrate_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data1_keymap],
                            'svgid':'svg2',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_filtrate_O = {'tileheader':'Filtrate data','tiletype':'svg','tileid':"tile2",'rowid':"row2",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        svgtileparameters_filtrate_O.update(svgparameters_filtrate_O);
        svgparameters_combined_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data1_keymap],
                            'svgid':'svg3',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_combined_O = {'tileheader':'Broth-Filtrate data','tiletype':'svg','tileid':"tile3",'rowid':"row2",'colid':"col3",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        svgtileparameters_combined_O.update(svgparameters_combined_O);
        # make the svg objects for the averages data
        svgparameters_averages_broth_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data2_keymap],
                            'svgid':'svg4',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
    						'svgformtileid':'filtermenu2','svgresetbuttonid':'reset2','svgsubmitbuttonid':'submit2'};
        svgtileparameters_averages_broth_O = {'tileheader':'Broth data','tiletype':'svg','tileid':"tile4",'rowid':"row3",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        svgtileparameters_averages_broth_O.update(svgparameters_averages_broth_O);
        svgparameters_averages_filtrate_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data3_keymap],
                            'svgid':'svg5',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
    						'svgformtileid':'filtermenu2','svgresetbuttonid':'reset2','svgsubmitbuttonid':'submit2'};
        svgtileparameters_averages_filtrate_O = {'tileheader':'Filtrate data','tiletype':'svg','tileid':"tile5",'rowid':"row3",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        svgtileparameters_averages_filtrate_O.update(svgparameters_averages_filtrate_O);
        svgparameters_averages_combined_O = {"svgtype":'boxandwhiskersplot2d_02',"svgkeymap":[data4_keymap],
                            'svgid':'svg6',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":250,"svgheight":250,
                            "svgx1axislabel":"component_name","svgy1axislabel":"concentration",
    						'svgformtileid':'filtermenu2','svgresetbuttonid':'reset2','svgsubmitbuttonid':'submit2'};
        svgtileparameters_averages_combined_O = {'tileheader':'Broth-Filtrate data','tiletype':'svg','tileid':"tile6",'rowid':"row3",'colid':"col3",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        svgtileparameters_averages_combined_O.update(svgparameters_averages_combined_O);
        # make the tables for the normalized and averages data
        tableparameters_normalized_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_normalized_O = {'tileheader':'normalized data','tiletype':'table','tileid':"tile7",'rowid':"row4",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_normalized_O.update(tableparameters_normalized_O);
        tableparameters_averages_O = {"tabletype":'responsivetable_01',
                    'tableid':'table2',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu2','tableresetbuttonid':'reset2','tablesubmitbuttonid':'submit2'};
        tabletileparameters_averages_O = {'tileheader':'averages data','tiletype':'table','tileid':"tile8",'rowid':"row5",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_averages_O.update(tableparameters_averages_O);
        parametersobject_O = [formtileparameters_normalized_O,
                              formtileparameters_averages_O,
                              svgtileparameters_broth_O,
                              svgtileparameters_filtrate_O,
                              svgtileparameters_combined_O,
                              svgtileparameters_averages_broth_O,
                              svgtileparameters_averages_filtrate_O,
                              svgtileparameters_averages_combined_O,
                              tabletileparameters_normalized_O,
                              tabletileparameters_averages_O];
        tile2datamap_O = {"filtermenu1":[2],"filtermenu2":[5],
                          "tile1":[0],"tile2":[1],"tile3":[2],
                          "tile4":[3],"tile5":[4],"tile6":[5],
                          "tile7":[2],"tile8":[5]};
        filtermenuobject_O = [{"filtermenuid":"filtermenu1","filtermenuhtmlid":"filtermenuform1",
                "filtermenusubmitbuttonid":"submit1","filtermenuresetbuttonid":"reset1",
                "filtermenuupdatebuttonid":"update1"},{"filtermenuid":"filtermenu2","filtermenuhtmlid":"filtermenuform2",
                "filtermenusubmitbuttonid":"submit2","filtermenuresetbuttonid":"reset2",
                "filtermenuupdatebuttonid":"update2"}
                              ];
        # dump the data to a json file
        data_str = 'var ' + 'data' + ' = ' + json.dumps(dataobject_O) + ';';
        parameters_str = 'var ' + 'parameters' + ' = ' + json.dumps(parametersobject_O) + ';';
        tile2datamap_str = 'var ' + 'tile2datamap' + ' = ' + json.dumps(tile2datamap_O) + ';';
        filtermenu_str = 'var ' + 'filtermenu' + ' = ' + json.dumps(filtermenuobject_O) + ';';
        #
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = filtermenuobject_O);
        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01ResequencingMutationsAnnotated_js(self,analysis_id_I,mutation_id_exclusion_list=[],frequency_threshold=0.1,max_position=4630000,data_dir_I="tmp"):
        '''export data_stage01_resequencing_mutationsAnnotated to js file
        Visualization: treemap of the mutations
        '''
        
        print('exportingdataStage01ResequencingMutationsAnnotated...')
        
        genomediff = genome_diff();
        # get the analysis information
        experiment_ids,sample_names,time_points = [],[],[];
        experiment_ids,sample_names,time_points = self.get_experimentIDAndSampleNameAndTimePoint_analysisID_dataStage01ResequencingAnalysis(analysis_id_I);
        mutation_data_O = [];
        mutation_ids = [];
        for sample_name_cnt,sample_name in enumerate(sample_names):
            # query mutation data:
            mutations = [];
            mutations = self.get_mutations_experimentIDAndSampleName_dataStage01ResequencingMutationsAnnotated(experiment_ids[sample_name_cnt],sample_name);
            for end_cnt,mutation in enumerate(mutations):
                if mutation['mutation_position'] > max_position:
                    continue;
                if mutation['mutation_frequency']<frequency_threshold:
                    continue;
                if not mutation['mutation_genes']:
                    mutation['mutation_genes'] = ['unknown'];
                # mutation id
                mutation_id = genomediff._make_mutationID(mutation['mutation_genes'],mutation['mutation_type'],mutation['mutation_position']);
                if mutation_id in mutation_id_exclusion_list:
                    continue;
                tmp = {};
                tmp['analysis_id']=analysis_id_I;
                tmp['time_point']=time_points[sample_name_cnt]
                tmp['experiment_id']=experiment_ids[sample_name_cnt]
                tmp['sample_name']=sample_name
                tmp['mutation_id']=mutation_id;
                if mutation['mutation_annotations']:
                    tmp['mutation_annotations']=";".join([x for x in mutation['mutation_annotations'] if x is not None]);
                else: tmp['mutation_annotations']=mutation['mutation_annotations'];
                if mutation['mutation_links']:
                    tmp['mutation_links']=";".join([x for x in mutation['mutation_links'] if x is not None]);
                else: tmp['mutation_links']=mutation['mutation_links'];
                if mutation['mutation_genes']:
                    tmp['mutation_genes']=";".join([x for x in mutation['mutation_genes'] if x is not None]);
                else: tmp['mutation_genes']=mutation['mutation_genes'];
                if mutation['mutation_position']:
                    tmp['mutation_position']=mutation['mutation_position'];
                else: tmp['mutation_position']=mutation['mutation_position'];
                if mutation['mutation_locations']:
                    tmp['mutation_locations']=";".join([x for x in mutation['mutation_locations'] if x is not None]);
                else: tmp['mutation_locations']=mutation['mutation_locations'];
                tmp.update(mutation);
                mutation_data_O.append(tmp);

        # dump chart parameters to a js files
        data1_keys = [
                    'experiment_id',
                    'sample_name',
                    'mutation_id',
                    #'mutation_frequency',
                    'mutation_type',
                    'mutation_position',
                    #'mutation_data',
                    'mutation_annotations',
                    'mutation_genes',
                    #'mutation_links',
                    'mutation_locations'
                    ];
        data1_nestkeys = ['analysis_id',
                          'mutation_genes',
                          'mutation_position',
                          'mutation_type',
                          #'sample_name'
                          ];
        data1_keymap = {'xdata':'intermediate',
                        'ydata':'mutation_frequency',
                        'serieslabel':'mutation_id',
                        'featureslabel':''};
        # make the data object
        dataobject_O = [{"data":mutation_data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},
                        {"data":mutation_data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}
                        ];
        # make the tile parameter objects
        # tile 0: form
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        formparameters_O = {'htmlid':'filtermenuform1','htmltype':'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        # tile 1: treelayout2d_01
        svgparameters_O = {"svgtype":'treelayout2d_01',
                           "svgkeymap":[data1_keymap],
                            'svgid':'svg1',
                            "svgmargin":{ 'top': 100, 'right': 100, 'bottom': 100, 'left': 100 },
                            "svgwidth":1000,
                            "svgheight":1000,
                            "svgduration":750,
                            "datalastchild":'sample_name'
                            };
        svgtileparameters_O = {
                'tileheader':'Mutations annotated',
                'tiletype':'svg',
                'tileid':"tile1",
                'rowid':"row2",
                'colid':"col1",
                'tileclass':"panel panel-default",
                'rowclass':"row",
                'colclass':"col-sm-12"
                };
        svgtileparameters_O.update(svgparameters_O);

        # tile 2: table
        tableparameters_O = {
                    "tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    };
        tabletileparameters_O = {
                    'tileheader':'Mutations annotated',
                    'tiletype':'table',
                    'tileid':"tile2",
                    'rowid':"row3",
                    'colid':"col1",
                    'tileclass':"panel panel-default",
                    'rowclass':"row",
                    'colclass':"col-sm-12"
                    };
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
        tile2datamap_O = {"filtermenu1":[0],"tile1":[0],"tile2":[1]}; #pass two identical data objects to the treemap and table
        # dump the data to a json file
        data_str = 'var ' + 'data' + ' = ' + json.dumps(dataobject_O) + ';';
        parameters_str = 'var ' + 'parameters' + ' = ' + json.dumps(parametersobject_O) + ';';
        tile2datamap_str = 'var ' + 'tile2datamap' + ' = ' + json.dumps(tile2datamap_O) + ';';
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01ResequencingHistogram_js(self,analysis_id_I,single_plot_I=False,data_dir_I="tmp"):
        '''export data_stage01_resequencing_histogram to js file
        Visualization: histogram of bins for each feature
        '''

        #get the table data
        data_table_O = [];
        data_table_O = self.get_rows_analysisID_dataStage01ResequencingHistogram(analysis_id_I);
        #get the data as a dictionary for each feature
        data_dict_O = {};
        data_dict_O = self.get_rowsAsFeaturesDict_analysisID_dataStage01ResequencingHistogram(analysis_id_I);
        
        # initialize the ddt objects
        dataobject_O = [];
        parametersobject_O = [];
        tile2datamap_O = {};
        
        # visualization parameters
        data1_keys = ['feature_id',
                      'feature_units',
                      ];
        data1_nestkeys = [
            'bin'
            ];
        data1_keymap = {
                'xdata':'bin',
                'ydata':'frequency',
                'serieslabel':'feature_id',
                'featureslabel':'bin',
                'ydatalb':None,
                'ydataub':None};

        # make the tile parameter objects
        # tile 0: form
        formtileparameters_O = {
            'tileheader':'Filter menu',
            'tiletype':'html',
            'tileid':"filtermenu1",
            'rowid':"row1",
            'colid':"col1",
            'tileclass':"panel panel-default",
            'rowclass':"row",
            'colclass':"col-sm-12"};
        formparameters_O = {
            'htmlid':'filtermenuform1',
            'htmltype':'form_01',
            "formsubmitbuttonidtext":{'id':'submit1','text':'submit'},
            "formresetbuttonidtext":{'id':'reset1','text':'reset'},
            "formupdatebuttonidtext":{'id':'update1','text':'update'}
            };
        formtileparameters_O.update(formparameters_O);

        dataobject_O.append({"data":data_table_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
        parametersobject_O.append(formtileparameters_O);
        tile2datamap_O.update({"filtermenu1":[0]});

        # tile 1-n features: histogram
        if not single_plot_I:
            rowcnt = 1;
            colcnt = 1;
            cnt = 0;
            for k,v in data_dict_O.items():
                svgtileid = "tilesvg"+str(cnt);
                svgid = 'svg'+str(cnt);
                iter=cnt+1; #start at 1
                if (cnt % 2 == 0): 
                    rowcnt = rowcnt+1;#even 
                    colcnt = 1;
                else:
                    colcnt = colcnt+1;
                # make the svg object
                svgparameters1_O = {
                    "svgtype":'verticalbarschart2d_01',
                    "svgkeymap":[data1_keymap],
                    'svgid':'svg'+str(cnt),
                    "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                    "svgwidth":350,
                    "svgheight":250,
                    "svgy1axislabel":"frequency"            
                        };
                svgtileparameters1_O = {
                    'tileheader':'Histogram',
                    'tiletype':'svg',
                    'tileid':svgtileid,
                    'rowid':"row"+str(rowcnt),
                    'colid':"col"+str(colcnt),
                    'tileclass':"panel panel-default",
                    'rowclass':"row",
                    'colclass':"col-sm-6"};
                dataobject_O.append({"data":v,"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
                svgtileparameters1_O.update(svgparameters1_O);
                parametersobject_O.append(svgtileparameters1_O);
                tile2datamap_O.update({svgtileid:[iter]});
                cnt+=1;
        else:
            cnt = 0;
            svgtileid = "tilesvg"+str(cnt);
            svgid = 'svg'+str(cnt);
            rowcnt = 2;
            colcnt = 1;
            # make the svg object
            svgparameters1_O = {
                "svgtype":'verticalbarschart2d_01',
                "svgkeymap":[data1_keymap],
                'svgid':'svg'+str(cnt),
                "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                "svgwidth":350,
                "svgheight":250,
                "svgy1axislabel":"frequency"            
                    };
            svgtileparameters1_O = {
                'tileheader':'Histogram',
                'tiletype':'svg',
                'tileid':svgtileid,
                'rowid':"row"+str(rowcnt),
                'colid':"col"+str(colcnt),
                'tileclass':"panel panel-default",
                'rowclass':"row",
                'colclass':"col-sm-6"};
            svgtileparameters1_O.update(svgparameters1_O);
            parametersobject_O.append(svgparameters1_O);
            tile2datamap_O.update({svgtileid:[1]});
            
        # make the table object
        tableparameters1_O = {
            "tabletype":'responsivetable_01',
            'tableid':'table1',
            "tablefilters":None,
            "tableclass":"table  table-condensed table-hover",
    		'tableformtileid':'tile1',
            };
        tabletileparameters1_O = {
            'tileheader':'Histogram',
            'tiletype':'table',
            'tileid':"tabletile1",
            'rowid':"row"+str(rowcnt+1),
            'colid':"col1",
            'tileclass':"panel panel-default",
            'rowclass':"row",
            'colclass':"col-sm-12"
            };
        tabletileparameters1_O.update(tableparameters1_O);

        dataobject_O.append({"data":data_table_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys});
        parametersobject_O.append(tabletileparameters1_O);
        tile2datamap_O.update({"tabletile1":[0]})

        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01ResequencingMutationsAnnotatedLineageArea_js(self,analysis_id_I,mutation_id_exclusion_list=[],frequency_threshold=0.1,max_position=4630000,data_dir_I="tmp"):
        '''export data_stage01_resequencing_mutationsAnnotated to js file
        Visualization: scatterlineplot of mutation frequency across jump time
        '''
        
        genomediff = genome_diff();
        print('exportingdataStage01ResequencingMutationsAnnotated...')
        # get the analysis information
        experiment_ids,sample_names,time_points = [],[],[];
        experiment_ids,sample_names,time_points = self.get_experimentIDAndSampleNameAndTimePoint_analysisID_dataStage01ResequencingAnalysis(analysis_id_I);
        # convert time_point to intermediates
        time_points_int = [int(x) for x in time_points];
        intermediates,time_points,experiment_ids,sample_names = (list(t) for t in zip(*sorted(zip(time_points_int,time_points,experiment_ids,sample_names))))
        intermediates = [i for i,x in enumerate(intermediates)];
        mutation_data_O = [];
        mutation_ids = [];
        for sample_name_cnt,sample_name in enumerate(sample_names):
            # query mutation data:
            mutations = [];
            mutations = self.get_mutations_experimentIDAndSampleName_dataStage01ResequencingMutationsAnnotated(experiment_ids[sample_name_cnt],sample_name);
            for end_cnt,mutation in enumerate(mutations):
                if mutation['mutation_position'] > max_position: #ignore positions great than 4000000
                    continue;
                if mutation['mutation_frequency']<frequency_threshold:
                    continue;
                # mutation id
                mutation_id = genomediff._make_mutationID(mutation['mutation_genes'],mutation['mutation_type'],mutation['mutation_position']);
                #mutation_id = self._make_mutationID(mutation['mutation_genes'],mutation['mutation_type'],mutation['mutation_position']);
                tmp = {};
                tmp.update(mutation);
                tmp.update({'mutation_id':mutation_id});
                mutation_data_O.append(tmp);
                mutation_ids.append(mutation_id);
        # screen out mutations
        mutation_ids_screened = [x for x in mutation_ids if not x in mutation_id_exclusion_list];
        mutation_ids_unique = list(set(mutation_ids_screened));
        # get mutation information for all unique mutations
        mutation_ids_uniqueInfo = [];
        for mutation_id in mutation_ids_unique:
            for mutation in mutation_data_O:
                if mutation_id == mutation['mutation_id']:
                    tmp = {};
                    #tmp['mutation_id']=mutation['mutation_id']
                    #tmp['mutation_frequency']=mutation['mutation_frequency'];
                    #tmp['mutation_genes']=mutation['mutation_genes'];
                    #tmp['mutation_position']=mutation['mutation_position'];
                    #tmp['mutation_annotations']=mutation['mutation_annotations'];
                    #tmp['mutation_locations']=mutation['mutation_locations'];
                    #tmp['mutation_links']=mutation['mutation_links'];
                    #tmp['mutation_type']=mutation['mutation_type'];
                    tmp['mutation_id']=mutation['mutation_id'];
                    tmp['mutation_frequency']=mutation['mutation_frequency'];
                    if mutation['mutation_genes']:
                        tmp['mutation_genes']=";".join([x for x in mutation['mutation_genes'] if x is not None]);
                    else: tmp['mutation_genes']=mutation['mutation_genes'];
                    if mutation['mutation_position']:
                        tmp['mutation_position']=mutation['mutation_position'];
                    else: tmp['mutation_position']=mutation['mutation_position'];
                    if mutation['mutation_annotations']:
                        tmp['mutation_annotations']=";".join([x for x in mutation['mutation_annotations'] if x is not None]);
                    else: tmp['mutation_annotations']=mutation['mutation_annotations'];
                    if mutation['mutation_locations']:
                        tmp['mutation_locations']=";".join([x for x in mutation['mutation_locations'] if x is not None]);
                    else: tmp['mutation_locations']=mutation['mutation_locations'];
                    if mutation['mutation_links']:
                        tmp['mutation_links']=";".join([x for x in mutation['mutation_links'] if x is not None]);
                    else: tmp['mutation_links']=mutation['mutation_links'];
                    tmp['mutation_type']=mutation['mutation_type'];
                    tmp['used_']=mutation['used_'];
                    tmp['comment_']=mutation['comment_'];
                    mutation_ids_uniqueInfo.append(tmp);   
                    break;       
        data_O = [];
        # add in 0.0 frequency for mutations that are not found
        for sample_name_cnt,sample_name in enumerate(sample_names):
            for mutation_id in mutation_ids_uniqueInfo:
                tmp = {};
                tmp_fitted = {};
                tmp['mutation_id']=mutation_id['mutation_id']
                tmp['time_point']=time_points[sample_name_cnt]
                tmp['intermediate']=intermediates[sample_name_cnt]
                tmp['experiment_id']=experiment_ids[sample_name_cnt]
                tmp['sample_name']=sample_name
                tmp['mutation_frequency']=0.0;  
                tmp['mutation_genes']=mutation_id['mutation_genes'];
                tmp['mutation_position']=mutation_id['mutation_position'];
                tmp['mutation_annotations']=mutation_id['mutation_annotations'];
                tmp['mutation_locations']=mutation_id['mutation_locations'];
                tmp['mutation_links']=mutation_id['mutation_links'];
                tmp['mutation_type']=mutation_id['mutation_type'];
                tmp['used_']=mutation_id['used_'];
                tmp['comment_']=mutation_id['comment_'];
                for mutation in mutation_data_O:
                    if sample_name == mutation['sample_name'] and mutation_id['mutation_id'] == mutation['mutation_id']:
                        tmp['mutation_frequency']=mutation['mutation_frequency'];
                        tmp['comment_']=mutation['comment_'];
                        break;
                data_O.append(tmp);
        # dump chart parameters to a js files
        data1_keys = [
                    #'experiment_id',
                    #'sample_name',
                    'mutation_id',
                    #'mutation_frequency',
                    'mutation_type',
                    'mutation_position',
                    #'mutation_data',
                    #'mutation_annotations',
                    'mutation_genes',
                    #'mutation_links',
                    'mutation_locations'
                    ];
        data1_nestkeys = ['mutation_id']; #horizontalareaplot2d_01
        #data1_nestkeys = ['intermediate']; #verticalbarschart2d_01
        data1_keymap = {'xdata':'intermediate',
                        'ydata':'mutation_frequency',
                        'serieslabel':'mutation_id',
                        'featureslabel':''};
        parameters = {"chart1margin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                    "chart1width":500,"chart1height":350,
                  "chart1title":"Population mutation frequency", "chart1x1axislabel":"jump_time_point","chart1y1axislabel":"frequency"}
        # make the data object
        dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys},{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        formparameters_O = {'htmlid':'filtermenuform1','htmltype':'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        svgparameters_O = {
            #"svgtype":'verticalbarschart2d_01',
            "svgtype":'horizontalareaplot2d_01',
            "svgkeymap":[data1_keymap,data1_keymap],
            'svgid':'svg1',
            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
            "svgwidth":500,"svgheight":350,
            "svgstackoffset":"extend",
            "svgx1axislabel":"jump_time_point","svgy1axislabel":"frequency",
    		'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_O = {'tileheader':'Population mutation frequency','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
        svgtileparameters_O.update(svgparameters_O);
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'Population mutation frequency','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
        tile2datamap_O = {"filtermenu1":[0],"tile2":[0],"tile3":[0]};
        # dump the data to a json file

        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = None);
        if data_dir_I=='tmp':
            filename_str = self.settings['visualization_data'] + '/tmp/ddt_data.js'
        elif data_dir_I=='project':
            filename_str = self.settings['visualization_data'] + '/project/' + analysis_id_I + '_data_stage01_resequencing_mutationsAnnotated' + '.js'
        elif data_dir_I=='data_json':
            data_json_O = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());
    def export_dataStage01ResequencingAmplifications_js(self, analysis_id_I, data_dir_I="tmp"):
        """export amplifications and statistics to js file"""

        ddtutilities = ddt_container()
        # get the analysis info
        # analysis_info = {};
        # analysis_info = self.get_analysis_analysisID_dataStage01ResequencingAnalysis(analysis_id_I);
        experiment_ids = []
        lineage_names = []
        sample_names = []
        time_points = []
        experiment_ids, lineage_names, sample_names, time_points = self.get_experimentIDAndLineageNameAndSampleNameAndTimePoint_analysisID_dataStage01ResequencingAnalysis(
            analysis_id_I
        )
        # convert time_point to intermediates
        time_points_int = [int(x) for x in time_points]
        intermediates, time_points, experiment_ids, sample_names, lineage_names = (
            list(t)
            for t in zip(*sorted(zip(time_points_int, time_points, experiment_ids, sample_names, lineage_names)))
        )
        intermediates = [i for i, x in enumerate(intermediates)]
        # get the data for the analysis
        data1_O = []
        data2_O = []
        data3_O = []
        for sn_cnt, sn in enumerate(sample_names):
            data1_tmp = []
            data1_tmp = self.get_rows_experimentIDAndSampleName_dataStage01ResequencingAmplifications_visualization(
                experiment_ids[sn_cnt], sn
            )
            data1_O.extend(ddtutilities.make_listDict_JSONAndJSCompatible(data1_tmp))
            data2_tmp = []
            data2_tmp = self.get_rows_experimentIDAndSampleName_dataStage01ResequencingAmplificationStats(
                experiment_ids[sn_cnt], sn
            )
            data2_O.extend(ddtutilities.make_listDict_JSONAndJSCompatible(data2_tmp))
            data3_tmp = []
            data3_tmp = self.get_rows_experimentIDAndSampleName_dataStage01ResequencingAmplificationAnnotations(
                experiment_ids[sn_cnt], sn
            )
            data3_O.extend(ddtutilities.make_listDict_JSONAndJSCompatible(data3_tmp))
        # dump chart parameters to a js files
        data1_keys = [
            "experiment_id",
            "sample_name",
            "genome_chromosome",
            "genome_strand",
            "amplification_start",
            "amplification_stop",
            "sample_name_strand",
        ]
        data1_nestkeys = [
            #'sample_name',
            "genome_strand"
        ]
        data1_keymap = {
            "xdata": "genome_index",
            "ydata": "reads",
            "serieslabel": "sample_name_strand",  # custom for vis
            #'serieslabel':'genome_strand',
            "featureslabel": "reads",
        }
        data2_keys = [
            "experiment_id",
            "sample_name",
            "genome_chromosome",
            "genome_strand",
            #'reads_min',
            #'reads_max',
            #'reads_lb',
            #'reads_ub',
            #'reads_iq1',
            #'reads_iq3',
            #'reads_median',
            #'reads_mean',
            #'reads_var',
            #'reads_n',
            "amplification_start",
            "amplification_stop",
        ]
        data2_nestkeys = ["sample_name"]
        data2_keymap = {
            "xdata": "genome_index",
            "ydata": "reads",
            "serieslabel": "genome_strand",
            "featureslabel": "reads",
        }
        data3_keys = [
            "experiment_id",
            "sample_name",
            "genome_chromosome",
            "genome_strand",
            "feature_annotations",
            "feature_genes",
            "feature_locations",
            "feature_links",
            "feature_start",
            "feature_stop",
            "feature_types",
            "amplification_start",
            "amplification_stop",
        ]
        data3_nestkeys = ["sample_name"]
        data3_keymap = {
            "xdata": "genome_index",
            "ydata": "reads",
            "serieslabel": "genome_strand",
            "featureslabel": "reads",
        }
        # make the data object
        dataobject_O = [
            {"data": data1_O, "datakeys": data1_keys, "datanestkeys": data1_nestkeys},
            {"data": data2_O, "datakeys": data2_keys, "datanestkeys": data2_nestkeys},
            {"data": data3_O, "datakeys": data3_keys, "datanestkeys": data3_nestkeys},
        ]
        # make the tile parameter objects
        # linked set #1
        formtileparameters_O = {
            "tileheader": "Filter menu",
            "tiletype": "html",
            "tileid": "filtermenu1",
            "rowid": "row1",
            "colid": "col1",
            "tileclass": "panel panel-default",
            "rowclass": "row",
            "colclass": "col-sm-4",
        }
        formparameters_O = {
            "htmlid": "filtermenuform1",
            "htmltype": "form_01",
            "formsubmitbuttonidtext": {"id": "submit1", "text": "submit"},
            "formresetbuttonidtext": {"id": "reset1", "text": "reset"},
            "formupdatebuttonidtext": {"id": "update1", "text": "update"},
        }
        formtileparameters_O.update(formparameters_O)
        svgparameters_O = {
            "svgtype": "scatterplot2d_01",
            "svgkeymap": [data1_keymap, data1_keymap],
            "svgid": "svg1",
            "svgmargin": {"top": 50, "right": 150, "bottom": 50, "left": 50},
            "svgwidth": 500,
            "svgheight": 350,
            "svgx1axislabel": "index",
            "svgy1axislabel": "reads",
            "svgformtileid": "filtermenu1",
            "svgresetbuttonid": "reset1",
            "svgsubmitbuttonid": "submit1",
            "svgx1axistickformat": ".2e",
            "svgx1axisticktextattr": {
                "transform": "matrix(0,1,-1,0,16,6)",
                # "transform":'rotate(90)',"transform":'translate(0,10)'
            },
            "svgx1axisticktextstyle": {"text-anchor": "start"},
        }
        svgtileparameters_O = {
            "tileheader": "Amplifications",
            "tiletype": "svg",
            "tileid": "tile2",
            "rowid": "row1",
            "colid": "col2",
            "tileclass": "panel panel-default",
            "rowclass": "row",
            "colclass": "col-sm-8",
        }
        svgtileparameters_O.update(svgparameters_O)
        # linked set #2
        formtileparameters2_O = {
            "tileheader": "Filter menu",
            "tiletype": "html",
            "tileid": "filtermenu2",
            "rowid": "row2",
            "colid": "col1",
            "tileclass": "panel panel-default",
            "rowclass": "row",
            "colclass": "col-sm-4",
        }
        formparameters2_O = {
            "htmlid": "filtermenuform2",
            "htmltype": "form_01",
            "formsubmitbuttonidtext": {"id": "submit2", "text": "submit"},
            "formresetbuttonidtext": {"id": "reset2", "text": "reset"},
            "formupdatebuttonidtext": {"id": "update2", "text": "update"},
        }
        formtileparameters2_O.update(formparameters2_O)
        tableparameters_O = {
            "tabletype": "responsivetable_01",
            "tableid": "table1",
            "tablefilters": None,
            "tableclass": "table  table-condensed table-hover",
            "tableformtileid": "filtermenu2",
            "tableresetbuttonid": "reset2",
            "tablesubmitbuttonid": "submit2",
        }
        tabletileparameters_O = {
            "tileheader": "Amplification statistics",
            "tiletype": "table",
            "tileid": "tile3",
            "rowid": "row2",
            "colid": "col2",
            "tileclass": "panel panel-default",
            "rowclass": "row",
            "colclass": "col-sm-12",
        }
        tabletileparameters_O.update(tableparameters_O)
        # linked set #3
        formtileparameters3_O = {
            "tileheader": "Filter menu",
            "tiletype": "html",
            "tileid": "filtermenu3",
            "rowid": "row3",
            "colid": "col1",
            "tileclass": "panel panel-default",
            "rowclass": "row",
            "colclass": "col-sm-4",
        }
        formparameters3_O = {
            "htmlid": "filtermenuform3",
            "htmltype": "form_01",
            "formsubmitbuttonidtext": {"id": "submit3", "text": "submit"},
            "formresetbuttonidtext": {"id": "reset3", "text": "reset"},
            "formupdatebuttonidtext": {"id": "update3", "text": "update"},
        }
        formtileparameters3_O.update(formparameters3_O)
        tableparameters2_O = {
            "tabletype": "responsivetable_01",
            "tableid": "table2",
            "tablefilters": None,
            "tableclass": "table  table-condensed table-hover",
            "tableformtileid": "filtermenu3",
            "tableresetbuttonid": "reset3",
            "tablesubmitbuttonid": "submit3",
        }
        tabletileparameters2_O = {
            "tileheader": "Amplification annotations",
            "tiletype": "table",
            "tileid": "tile4",
            "rowid": "row3",
            "colid": "col2",
            "tileclass": "panel panel-default",
            "rowclass": "row",
            "colclass": "col-sm-12",
        }
        tabletileparameters2_O.update(tableparameters2_O)
        parametersobject_O = [
            formtileparameters_O,
            svgtileparameters_O,
            formtileparameters2_O,
            tabletileparameters_O,
            formtileparameters3_O,
            tabletileparameters2_O,
        ]
        tile2datamap_O = {
            "filtermenu1": [0],
            "tile2": [0, 0],
            "tile3": [1],
            "tile4": [2],
            "filtermenu2": [1],
            "filtermenu3": [2],
        }
        filtermenuobject_O = [
            {
                "filtermenuid": "filtermenu1",
                "filtermenuhtmlid": "filtermenuform1",
                "filtermenusubmitbuttonid": "submit1",
                "filtermenuresetbuttonid": "reset1",
                "filtermenuupdatebuttonid": "update1",
            },
            {
                "filtermenuid": "filtermenu2",
                "filtermenuhtmlid": "filtermenuform2",
                "filtermenusubmitbuttonid": "submit2",
                "filtermenuresetbuttonid": "reset2",
                "filtermenuupdatebuttonid": "update2",
            },
            {
                "filtermenuid": "filtermenu3",
                "filtermenuhtmlid": "filtermenuform3",
                "filtermenusubmitbuttonid": "submit3",
                "filtermenuresetbuttonid": "reset3",
                "filtermenuupdatebuttonid": "update3",
            },
        ]
        # dump the data to a json file
        ddtutilities = ddt_container(
            parameters_I=parametersobject_O,
            data_I=dataobject_O,
            tile2datamap_I=tile2datamap_O,
            filtermenu_I=filtermenuobject_O,
        )
        if data_dir_I == "tmp":
            filename_str = self.settings["visualization_data"] + "/tmp/ddt_data.js"
        elif data_dir_I == "data_json":
            data_json_O = ddtutilities.get_allObjects_js()
            return data_json_O
        with open(filename_str, "w") as file:
            file.write(ddtutilities.get_allObjects())
    def export_boxAndWhiskersPlot_peakResolution_js(self,experiment_id_I,
                            component_name_pairs_I=[],
                            peakInfo_parameter_I = ['rt_dif','resolution'],
                            data_dir_I='tmp'):
        '''Export data for a box and whiskers plot'''

        print('export_boxAndWhiskersPlot...')
        data_O=[];
        if peakInfo_parameter_I:
            peakInfo_parameter = peakInfo_parameter_I;
        else:
            peakInfo_parameter = [];
            peakInfo_parameter = self.get_peakInfoParameter_experimentID_dataStage01PeakResolution(experiment_id_I);
        for parameter in peakInfo_parameter:
            if component_name_pairs_I:
                component_name_pairs = component_name_pairs_I;
            else:
                component_name_pairs = [];
                component_name_pairs = self.get_componentNamePairs_experimentIDAndPeakInfoParameter_dataStage01PeakResolution(experiment_id_I,parameter);
            for cn in component_name_pairs:
                # get the data 
                row = {};
                row = self.get_row_experimentIDAndPeakInfoParameterComponentName_dataStage01PeakResolution(experiment_id_I,parameter,cn)
                if row and row['peakInfo_ave']:
                    #TODO: fix type in database 'acqusition_date_and_times'
                    tmp_list = [];
                    for d in row['acqusition_date_and_times']:
                        tmp = None;
                        tmp = self.convert_datetime2string(d);
                        tmp_list.append(tmp);
                    row['acqusition_date_and_times'] = tmp_list;
                    data_O.append(row);
        # dump chart parameters to a js files
        data1_keys = ['experiment_id',
                    'component_group_name_pair',
                    'component_name_pair',
                    'peakInfo_parameter',
                    #'peakInfo_ave',
                    #'peakInfo_cv',
                    #'peakInfo_lb',
                    #'peakInfo_ub',
                    #'peakInfo_units',
                    'sample_names',
                    'sample_types',
                    #'acqusition_date_and_times'
                    ];
        data1_nestkeys = ['component_name_pair'];
        data1_keymap = {'xdata':'component_name_pair',
                        'ydatamean':'peakInfo_ave',
                        'ydatalb':'peakInfo_lb',
                        'ydataub':'peakInfo_ub',
                        #'ydatamin':None,
                        #'ydatamax':None,
                        #'ydataiq1':None,
                        #'ydataiq3':None,
                        #'ydatamedian':None,
                        'serieslabel':'peakInfo_parameter',
                        'featureslabel':'component_name_pair'};
        # make the data object
        dataobject_O = [{"data":data_O,"datakeys":data1_keys,"datanestkeys":data1_nestkeys}];
        # make the tile parameter objects
        formtileparameters_O = {'tileheader':'Filter menu','tiletype':'html','tileid':"filtermenu1",'rowid':"row1",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-4"};
        formparameters_O = {'htmlid':'filtermenuform1',"htmltype":'form_01',"formsubmitbuttonidtext":{'id':'submit1','text':'submit'},"formresetbuttonidtext":{'id':'reset1','text':'reset'},"formupdatebuttonidtext":{'id':'update1','text':'update'}};
        formtileparameters_O.update(formparameters_O);
        svgparameters_O = {"svgtype":'boxandwhiskersplot2d_01',"svgkeymap":[data1_keymap],
                            'svgid':'svg1',
                            "svgmargin":{ 'top': 50, 'right': 150, 'bottom': 50, 'left': 50 },
                            "svgwidth":500,"svgheight":350,
                            "svgx1axislabel":"component_name_pair","svgy1axislabel":"parameter_value",
    						'svgformtileid':'filtermenu1','svgresetbuttonid':'reset1','svgsubmitbuttonid':'submit1'};
        svgtileparameters_O = {'tileheader':'Custom box and whiskers plot','tiletype':'svg','tileid':"tile2",'rowid':"row1",'colid':"col2",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-8"};
        svgtileparameters_O.update(svgparameters_O);
        tableparameters_O = {"tabletype":'responsivetable_01',
                    'tableid':'table1',
                    "tablefilters":None,
                    "tableclass":"table  table-condensed table-hover",
    			    'tableformtileid':'filtermenu1','tableresetbuttonid':'reset1','tablesubmitbuttonid':'submit1'};
        tabletileparameters_O = {'tileheader':'peakResolution','tiletype':'table','tileid':"tile3",'rowid':"row2",'colid':"col1",
            'tileclass':"panel panel-default",'rowclass':"row",'colclass':"col-sm-12"};
        tabletileparameters_O.update(tableparameters_O);
        parametersobject_O = [formtileparameters_O,svgtileparameters_O,tabletileparameters_O];
        tile2datamap_O = {"filtermenu1":[0],"tile2":[0],"tile3":[0]};
        # dump the data to a json file
        ddtutilities = ddt_container(parameters_I = parametersobject_O,data_I = dataobject_O,tile2datamap_I = tile2datamap_O,filtermenu_I = 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 = ddtutilities.get_allObjects_js();
            return data_json_O;
        with open(filename_str,'w') as file:
            file.write(ddtutilities.get_allObjects());