def InitUI(self):
        """
        initialize window
        """
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)

        if self.grid_type in self.contribution.tables:
            dataframe = self.contribution.tables[self.grid_type]
        else:
            dataframe = None
        self.grid_builder = GridBuilder(self.contribution, self.grid_type,
                                        self.panel, parent_type=self.parent_type,
                                        reqd_headers=self.reqd_headers,
                                        exclude_cols=self.exclude_cols,
                                        huge=self.huge)

        self.grid = self.grid_builder.make_grid()
        self.grid.InitUI()


        ## Column management buttons
        self.add_cols_button = wx.Button(self.panel, label="Add additional columns",
                                         name='add_cols_btn',
                                         size=(170, 20))
        self.Bind(wx.EVT_BUTTON, self.on_add_cols, self.add_cols_button)
        self.remove_cols_button = wx.Button(self.panel, label="Remove columns",
                                            name='remove_cols_btn',
                                            size=(170, 20))

        self.Bind(wx.EVT_BUTTON, self.on_remove_cols, self.remove_cols_button)

        ## Row management buttons
        self.remove_row_button = wx.Button(self.panel, label="Remove last row",
                                           name='remove_last_row_btn')
        self.Bind(wx.EVT_BUTTON, self.on_remove_row, self.remove_row_button)
        many_rows_box = wx.BoxSizer(wx.HORIZONTAL)
        self.add_many_rows_button = wx.Button(self.panel, label="Add row(s)",
                                              name='add_many_rows_btn')
        self.rows_spin_ctrl = wx.SpinCtrl(self.panel, value='1', initial=1,
                                          name='rows_spin_ctrl')
        many_rows_box.Add(self.add_many_rows_button, flag=wx.ALIGN_CENTRE)
        many_rows_box.Add(self.rows_spin_ctrl)
        self.Bind(wx.EVT_BUTTON, self.on_add_rows, self.add_many_rows_button)

        self.deleteRowButton = wx.Button(self.panel, id=-1,
                                         label='Delete selected row(s)',
                                         name='delete_row_btn')
        self.Bind(wx.EVT_BUTTON, lambda event: self.on_remove_row(event, False), self.deleteRowButton)
        self.deleteRowButton.Disable()

        # measurements table should not be able to add new rows
        # that should be done elsewhere
        if self.huge:
            self.add_many_rows_button.Disable()
            self.rows_spin_ctrl.Disable()
            self.remove_row_button.Disable()
            # can't remove cols (seg fault), but can add them
            #self.add_cols_button.Disable()
            self.remove_cols_button.Disable()


        ## Data management buttons
        self.importButton = wx.Button(self.panel, id=-1,
                                      label='Import MagIC-format file',
                                      name='import_btn')
        self.Bind(wx.EVT_BUTTON, self.onImport, self.importButton)
        self.exitButton = wx.Button(self.panel, id=-1,
                                    label='Save and close grid',
                                    name='save_and_quit_btn')
        self.Bind(wx.EVT_BUTTON, self.onSave, self.exitButton)
        self.cancelButton = wx.Button(self.panel, id=-1, label='Cancel',
                                      name='cancel_btn')
        self.Bind(wx.EVT_BUTTON, self.onCancelButton, self.cancelButton)
        self.Bind(wx.EVT_CLOSE, self.onCancelButton)

        ## Input/output buttons
        self.copyButton = wx.Button(self.panel, id=-1,
                                     label="Start copy mode",
                                     name="copy_mode_btn")
        self.Bind(wx.EVT_BUTTON, self.onCopyMode, self.copyButton)
        self.selectAllButton = wx.Button(self.panel, id=-1,
                                         label="Copy all cells",
                                         name="select_all_btn")
        self.Bind(wx.EVT_BUTTON, self.onSelectAll, self.selectAllButton)
        self.copySelectionButton = wx.Button(self.panel, id=-1,
                                         label="Copy selected cells",
                                         name="copy_selection_btn")
        self.Bind(wx.EVT_BUTTON, self.onCopySelection, self.copySelectionButton)
        self.copySelectionButton.Disable()

        ## Help message and button
        # button
        self.toggle_help_btn = wx.Button(self.panel, id=-1, label="Show help",
                                         name='toggle_help_btn')
        self.Bind(wx.EVT_BUTTON, self.toggle_help, self.toggle_help_btn)
        # message
        self.help_msg_boxsizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, name='help_msg_boxsizer'), wx.VERTICAL)

        if self.grid_type == 'measurements':
            self.default_msg_text = "Edit measurements here.\nIn general, measurements should be imported directly into Pmag GUI,\nwhich has protocols for converting many lab formats into the MagIC format.\nIf we are missing your particular lab format, please let us know: https://github.com/PmagPy/PmagPy/issues.\nThis grid is just meant for looking at your measurements and doing small edits.\nCurrently, you can't add/remove rows here.  You can add columns and edit cell values."
        else:
            self.default_msg_text = 'Edit {} here.\nYou can add or remove both rows and columns, however required columns may not be deleted.\nControlled vocabularies are indicated by **, and will have drop-down-menus.\nSuggested vocabularies are indicated by ^^, and also have drop-down-menus.\nTo edit all values in a column, click the column header.\nYou can cut and paste a block of cells from an Excel-like file.\nJust click the top left cell and use command "v".'.format(self.grid_type)
        txt = ''
        if self.grid_type == 'locations':
            txt = '\n\nNote: you can fill in location start/end latitude/longitude here.\nHowever, if you add sites in step 2, the program will calculate those values automatically,\nbased on site latitudes/logitudes.\nThese values will be written to your upload file.'
        if self.grid_type == 'samples':
            txt = "\n\nNote: you can fill in lithology, class, and type for each sample here.\nHowever, if the sample's class, lithology, and type are the same as its parent site,\nthose values will propagate down, and will be written to your sample file automatically."
        if self.grid_type == 'specimens':
            txt = "\n\nNote: you can fill in lithology, class, and type for each specimen here.\nHowever, if the specimen's class, lithology, and type are the same as its parent sample,\nthose values will propagate down, and will be written to your specimen file automatically."
        if self.grid_type == 'ages':
            txt = "\n\nNote: only ages for which you provide data will be written to your upload file."
        self.default_msg_text += txt
        self.msg_text = wx.StaticText(self.panel, label=self.default_msg_text,
                                      style=wx.TE_CENTER, name='msg text')
        self.help_msg_boxsizer.Add(self.msg_text)
        self.help_msg_boxsizer.ShowItems(False)

        ## Code message and button
        # button
        self.toggle_codes_btn = wx.Button(self.panel, id=-1,
                                          label="Show method codes",
                                          name='toggle_codes_btn')
        self.Bind(wx.EVT_BUTTON, self.toggle_codes, self.toggle_codes_btn)
        # message
        self.code_msg_boxsizer = pw.MethodCodeDemystifier(self.panel, self.contribution.vocab)
        self.code_msg_boxsizer.ShowItems(False)

        ## Add content to sizers
        self.hbox = wx.BoxSizer(wx.HORIZONTAL)
        col_btn_vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='Columns',
                                                      name='manage columns'), wx.VERTICAL)
        row_btn_vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='Rows',
                                                      name='manage rows'), wx.VERTICAL)
        self.main_btn_vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='Manage data',
                                                            name='manage data'), wx.VERTICAL)
        input_output_vbox = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label='In/Out',
                                                           name='manage in out'), wx.VERTICAL)
        col_btn_vbox.Add(self.add_cols_button, flag=wx.ALL, border=5)
        col_btn_vbox.Add(self.remove_cols_button, flag=wx.ALL, border=5)
        row_btn_vbox.Add(many_rows_box, flag=wx.ALL, border=5)
        row_btn_vbox.Add(self.remove_row_button, flag=wx.ALL, border=5)
        row_btn_vbox.Add(self.deleteRowButton, flag=wx.ALL, border=5)
        self.main_btn_vbox.Add(self.importButton, flag=wx.ALL, border=5)
        self.main_btn_vbox.Add(self.exitButton, flag=wx.ALL, border=5)
        self.main_btn_vbox.Add(self.cancelButton, flag=wx.ALL, border=5)
        input_output_vbox.Add(self.copyButton, flag=wx.ALL, border=5)
        input_output_vbox.Add(self.selectAllButton, flag=wx.ALL, border=5)
        input_output_vbox.Add(self.copySelectionButton, flag=wx.ALL, border=5)
        self.hbox.Add(col_btn_vbox)
        self.hbox.Add(row_btn_vbox)
        self.hbox.Add(self.main_btn_vbox)
        self.hbox.Add(input_output_vbox)

        #self.panel.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.onLeftClickLabel, self.grid)
        self.grid.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.onLeftClickLabel, self.grid)
        #
        self.Bind(wx.EVT_KEY_DOWN, self.on_key_down)
        self.panel.Bind(wx.EVT_TEXT_PASTE, self.do_fit)
        # add actual data!
        self.grid_builder.add_data_to_grid(self.grid, self.grid_type)
        # fill in some default values
        self.grid_builder.fill_defaults()
        # set scrollbars
        self.grid.set_scrollbars()

        ## this would be a way to prevent editing
        ## some cells in age grid.
        ## with multiple types of ages, though,
        ## this doesn't make much sense
        #if self.grid_type == 'ages':
        #    attr = wx.grid.GridCellAttr()
        #    attr.SetReadOnly(True)
        #    self.grid.SetColAttr(1, attr)

        self.drop_down_menu = drop_down_menus.Menus(self.grid_type, self.contribution, self.grid)
        self.grid_box = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, name='grid container'), wx.VERTICAL)
        self.grid_box.Add(self.grid, 1, flag=wx.ALL|wx.EXPAND, border=5)

        # final layout, set size
        self.main_sizer.Add(self.hbox, flag=wx.ALL|wx.ALIGN_CENTER,#|wx.SHAPED,
                            border=20)
        self.main_sizer.Add(self.toggle_help_btn, 0,
                            flag=wx.BOTTOM|wx.ALIGN_CENTRE,#|wx.SHAPED,
                            border=5)
        self.main_sizer.Add(self.help_msg_boxsizer, 0,
                            flag=wx.BOTTOM|wx.ALIGN_CENTRE,
                            border=10)
        self.main_sizer.Add(self.toggle_codes_btn, 0,
                            flag=wx.BOTTOM|wx.ALIGN_CENTRE,#|wx.SHAPED,
                            border=5)
        self.main_sizer.Add(self.code_msg_boxsizer, 0,
                            flag=wx.BOTTOM|wx.ALIGN_CENTRE,#|wx.SHAPED,
                            border=5)
        self.main_sizer.Add(self.grid_box, 2, flag=wx.ALL|wx.ALIGN_CENTER|wx.EXPAND, border=10)
        self.panel.SetSizer(self.main_sizer)
        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        panel_sizer.Add(self.panel, 1, wx.EXPAND)
        self.SetSizer(panel_sizer)
        panel_sizer.Fit(self)
        ## this keeps sizing correct if the user resizes the window manually
        #self.Bind(wx.EVT_SIZE, self.do_fit)
#        self.Centre()
        self.Show()