private void loadCalibrationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var fd = new FolderBrowserDialog();

            if (fd.ShowDialog() == DialogResult.OK)
            {
                var adc_cal_fn  = String.Format("{0}_ADCCalibration.csv", Config.ProbeSN);
                var gain_cal_fn = String.Format("{0}_GainCalValues.csv", Config.ProbeSN);

                var adc_path  = Directory.GetFiles(fd.SelectedPath, "*" + adc_cal_fn);
                var gain_path = Directory.GetFiles(fd.SelectedPath, "*" + gain_cal_fn);

                if (adc_path.Length != 0 && gain_path.Length != 0)
                {
                    // Check serial numbers inside each file
                    System.IO.StreamReader file = new System.IO.StreamReader(adc_path[0]);
                    var sn = UInt64.Parse(file.ReadLine());
                    file.Close();
                    if (Config.ProbeSN != sn)
                    {
                        ShowError("Serial number mismatch",
                                  String.Format("Serial number inside ADC calibration file, {0}," +
                                                "does not match the current probe serial number, {1}.", sn, Config.ProbeSN));
                    }

                    file = new System.IO.StreamReader(gain_path[0]);
                    sn   = UInt64.Parse(file.ReadLine());
                    file.Close();
                    if (Config.ProbeSN != sn)
                    {
                        ShowError("Serial number mismatch",
                                  String.Format("Serial number inside gain values file, {0}," +
                                                "does not match the current probe serial number, {1}.", sn, Config.ProbeSN));
                    }

                    // Parse ADC calibrations
                    CsvParserOptions csv_parser_opts = new CsvParserOptions(true, ',');
                    var adc_csv_mapper = new CsvNeuropixelsADCMapping();
                    var adc_csv_parser = new CsvParser <NeuropixelsADC>(csv_parser_opts, adc_csv_mapper);

                    // Parse ADC calibration parameters
                    var adcs = adc_csv_parser
                               .ReadFromFile(adc_path[0], Encoding.ASCII)
                               .ToList();

                    // Confirm parse
                    if (!adcs.All(x => x.IsValid))
                    {
                        ShowError("Parse Error", adcs.First(x => !x.IsValid).Error.Value);
                        return;
                    }

                    // Check length
                    if (adcs.Count() != Config.ADCs.Length)
                    {
                        ShowError("Parse Error",
                                  String.Format("Too many rows in ADC calibration file. There are {0} when " +
                                                "there should be {1}.", adcs.Count(), Config.ADCs.Length));
                        return;
                    }

                    // Parse Gains
                    var electrde_csv_mapper = new CsvNeuropixelsElectrodeMapping();
                    var electrde_csv_parser = new CsvParser <NeuropixelsElectrode>(csv_parser_opts, electrde_csv_mapper);

                    // Parse ADC calibration parameters
                    var electrodes = electrde_csv_parser
                                     .ReadFromFile(gain_path[0], Encoding.ASCII)
                                     .ToList();

                    // Confirm parse
                    if (!adcs.All(x => x.IsValid))
                    {
                        ShowError("Parse Error", electrodes.First(x => !x.IsValid).Error.Value);
                        return;
                    }

                    // Check length
                    if (electrodes.Count() != Config.Electrodes.Length)
                    {
                        ShowError("Parse Error",
                                  String.Format("Too many rows in gain values calibration file. There are {0} when " +
                                                "there should be {1}.", electrodes.Count(), Config.Electrodes.Length));
                        return;
                    }

                    // Assign
                    Config.ADCs       = adcs.Select(x => x.Result).ToArray();
                    Config.Electrodes = electrodes.Select(x => x.Result).ToArray();

                    // Update gridviews
                    dataGridView_ADCs.DataSource       = Config.ADCs;
                    dataGridView_Electrodes.DataSource = Config.Electrodes;
                }
                else
                {
                    ShowError("Missing calibration files", String.Format("One or both of the calibration" +
                                                                         " files matching the current probe serial number, {0} and {1}, were not found in the " +
                                                                         "specified directory.", adc_cal_fn, gain_cal_fn));
                    return;
                }
            }
        }
        private void loadCalibrationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var fd = new FolderBrowserDialog {
                ShowNewFolderButton = false
            };

            if (Config.CalibrationFolderPath != null && Directory.Exists(Config.CalibrationFolderPath))
            {
                fd.RootFolder   = Environment.SpecialFolder.Desktop;
                fd.SelectedPath = Config.CalibrationFolderPath;
            }

            fd.Description = String.Format("Select a folder containing the following calibration files:\n" +
                                           "* {0}_ADCCalibration.csv\n" +
                                           "* {0}_GainCalValues.csv", Config.FlexProbeSN);

            if (fd.ShowDialog() == DialogResult.OK)
            {
                var adc_cal_fn  = String.Format("{0}_ADCCalibration.csv", Config.FlexProbeSN);
                var gain_cal_fn = String.Format("{0}_GainCalValues.csv", Config.FlexProbeSN);

                var adc_path  = Directory.GetFiles(fd.SelectedPath, "*" + adc_cal_fn);
                var gain_path = Directory.GetFiles(fd.SelectedPath, "*" + gain_cal_fn);

                if (adc_path.Length != 0 && gain_path.Length != 0)
                {
                    // Check serial numbers inside each file
                    System.IO.StreamReader file = new System.IO.StreamReader(adc_path[0]);
                    Config.ConfigProbeSN = UInt64.Parse(file.ReadLine());
                    file.Close();
                    CheckStatus();

                    file = new System.IO.StreamReader(gain_path[0]);
                    Config.ConfigProbeSN = UInt64.Parse(file.ReadLine());
                    file.Close();
                    CheckStatus();

                    // Parse ADC calibrations
                    CsvParserOptions csv_parser_opts = new CsvParserOptions(true, ',');
                    var adc_csv_mapper = new CsvNeuropixelsADCMapping();
                    var adc_csv_parser = new CsvParser <NeuropixelsV1ADC>(csv_parser_opts, adc_csv_mapper);

                    // Parse ADC calibration parameters
                    var adcs = adc_csv_parser
                               .ReadFromFile(adc_path[0], Encoding.ASCII)
                               .ToList();

                    // Confirm parse
                    if (!adcs.All(x => x.IsValid))
                    {
                        ShowError("Parse Error", adcs.First(x => !x.IsValid).Error.Value);
                        return;
                    }

                    // Check length
                    if (adcs.Count() != Config.ADCs.Length)
                    {
                        ShowError("Parse Error",
                                  String.Format("Too many rows in ADC calibration file. There are {0} when " +
                                                "there should be {1}.", adcs.Count(), Config.ADCs.Length));
                        return;
                    }

                    // Parse Gains
                    var electrde_csv_mapper = new CsvNeuropixelsElectrodeMapping();
                    var electrde_csv_parser = new CsvParser <NeuropixelsV1GainCorrection>(csv_parser_opts, electrde_csv_mapper);

                    // Parse ADC calibration parameters
                    var electrodes = electrde_csv_parser
                                     .ReadFromFile(gain_path[0], Encoding.ASCII)
                                     .ToList();

                    // Confirm parse
                    if (!electrodes.All(x => x.IsValid))
                    {
                        ShowError("Parse Error", electrodes.First(x => !x.IsValid).Error.Value);
                        return;
                    }

                    // Check length
                    if (electrodes.Count() != NeuropixelsV1Probe.ELECTRODE_COUNT)
                    {
                        ShowError("Parse Error",
                                  String.Format("Incorrect number of gain correction values in calibration file. There are {0} when " +
                                                "there should be {1}.", electrodes.Count(), NeuropixelsV1Probe.ELECTRODE_COUNT));
                        return;
                    }

                    // Assign
                    Config.ADCs = adcs.Select(x => x.Result).ToArray();

                    foreach (var c in Config.Channels)
                    {
                        c.UpdateGainCorrections(electrodes.Select(x => x.Result).ToArray());
                    }

                    // Update gridviews
                    dataGridView_ADCs.DataSource = Config.ADCs;

                    // Save for next time
                    Config.CalibrationFolderPath = fd.SelectedPath;

                    // You need to upload these values
                    Config.RefreshNeeded = true;
                }
                else
                {
                    ShowError("Missing calibration files", String.Format("One or both of the calibration" +
                                                                         " files matching the current probe serial number, {0} and {1}, were not found in the " +
                                                                         "specified directory.", adc_cal_fn, gain_cal_fn));
                    return;
                }
            }
        }