Загрузка данных


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCharts/QLineSeries>
#include <QtCharts/QValueAxis>
#include <fstream>
#include <cmath>
#include <QString>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    chartView = new QChartView(this);
    ui->gridLayout->addWidget(chartView);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_loadData_clicked()
{
    std::fstream file("/home/robot33-19/Documents/Korenkov_A._433/data/test_data.txt"); 
    float x, y;
    data.clear(); 

    while(file >> x >> y) {
        data.push_back({x, y});
    }
    file.close();

    ui->label_status->setText("Загружено: " + QString::number(data.size()) + " измерений"); 
}

// === КНОПКА 1: График исходных данных ===
void MainWindow::on_pushButton_show_clicked()
{
    if (data.empty()) return; 

    QChart *chart = new QChart();
    QLineSeries *line_series = new QLineSeries();
    line_series->setName("Измерения");
    
    float x_min = 1e18, x_max = -1e18, y_min = 1e18, y_max = -1e18;

    for (int i = 0; i < (int)data.size(); i++) {
        std::pair<float,float> current = data.at(i);
        if(current.first < x_min) x_min = current.first;
        if(current.second > y_max) y_max = current.second;
        if(current.first > x_max) x_max = current.first;
        if(current.second < y_min) y_min = current.second;
        line_series->append(current.first, current.second);
    }

    int n = data.size();
    float sum_y = 0;
    for (int i = 0; i < n; i++) sum_y += data.at(i).second;
    float mean = sum_y / n;

    float sum_sq_diff = 0;
    for (int i = 0; i < n; i++) sum_sq_diff += std::pow(data.at(i).second - mean, 2);
    float std_dev = std::sqrt(sum_sq_diff / (n - 1));
    float error = 2.093 * (std_dev / std::sqrt(n));

    QValueAxis *axisX = new QValueAxis();
    QValueAxis *axisY = new QValueAxis();
    axisX->setRange(x_min, x_max);
    
    float y_pad = (y_max - y_min) * 0.1;
    if (y_pad == 0) y_pad = 1.0;
    axisY->setRange(y_min - y_pad, y_max + y_pad);

    chart->addAxis(axisX, Qt::AlignBottom);
    chart->addAxis(axisY, Qt::AlignRight);

    chart->addSeries(line_series);
    line_series->attachAxis(axisX); line_series->attachAxis(axisY);

    // ВАЖНО: 6 знаков после запятой, чтобы интервал не округлялся в нули!
    QString stats = QString("Среднее (Y): %1\nСКО: %2\nДов. интервал 95%: [%3; %4]")
                    .arg(mean, 0, 'f', 6).arg(std_dev, 0, 'f', 6)
                    .arg(mean - error, 0, 'f', 6).arg(mean + error, 0, 'f', 6);
    ui->label_stats->setText(stats);

    chart->setTitle("Исходные данные");
    chartView->setChart(chart);
}

// === КНОПКА 2: График СТРОГО в границах доверительного интервала ===
void MainWindow::on_pushButton_bell_clicked()
{
    if (data.size() < 2) return; 

    int n = data.size();
    float sum_y = 0;
    for (int i = 0; i < n; i++) sum_y += data.at(i).second;
    float mean = sum_y / n; 

    float sum_sq_diff = 0;
    for (int i = 0; i < n; i++) sum_sq_diff += std::pow(data.at(i).second - mean, 2);
    float std_dev = std::sqrt(sum_sq_diff / (n - 1)); 
    float error = 2.093 * (std_dev / std::sqrt(n));
    float nu = n - 1; 

    float pi = 3.14159265358979323846;
    float coef = std::tgamma((nu + 1.0) / 2.0) / (std::sqrt(nu * pi) * std::tgamma(nu / 2.0));

    QChart *chart = new QChart();
    chart->legend()->hide(); 

    QLineSeries *bell_series = new QLineSeries();
    QPen bellPen(Qt::blue); 
    bellPen.setWidth(2);
    bell_series->setPen(bellPen);

    // ЖЕСТКАЯ ПРИВЯЗКА: Строим график только от левой цифры до правой!
    float x_start = mean - error;
    float x_end = mean + error;
    float step = (x_end - x_start) / 200.0; 
    float max_y = 0;

    for (int i = 0; i <= 200; i++) {
        float x = x_start + i * step;
        float t = (x - mean) / std_dev;
        float pdf = (coef * std::pow(1.0 + (t * t) / nu, -(nu + 1.0) / 2.0)) / std_dev;

        bell_series->append(x, pdf);
        if (pdf > max_y) max_y = pdf;
    }

    QValueAxis *axisX = new QValueAxis();
    QValueAxis *axisY = new QValueAxis();
    
    // Оси теперь математически идентичны текстовому выводу
    axisX->setRange(x_start, x_end);
    axisY->setRange(0, max_y * 1.1); 

    chart->addAxis(axisX, Qt::AlignBottom);
    chart->addAxis(axisY, Qt::AlignLeft);

    chart->addSeries(bell_series);
    bell_series->attachAxis(axisX); 
    bell_series->attachAxis(axisY);

    // ВАЖНО: 6 знаков после запятой, чтобы интервал совпадал с графиком
    QString stats = QString("Среднее (Y): %1\nСКО: %2\nДов. интервал 95%: [%3; %4]")
                    .arg(mean, 0, 'f', 6).arg(std_dev, 0, 'f', 6)
                    .arg(mean - error, 0, 'f', 6).arg(mean + error, 0, 'f', 6);
    ui->label_stats->setText(stats);

    chart->setTitle("Плотность распределения Стьюдента (строго внутри интервала)");
    chartView->setChart(chart);
}