본문 바로가기

MATLAB/ㄴ 앱 디자이너

사용자가 선택한 항목을 기반으로 플롯을 업데이트하는 자동 재배치 기능이 있는 앱

 

https://kr.mathworks.com/help/matlab/creating_guis/data-analysis-app-or-gui.html

 

사용자가 선택한 항목을 기반으로 플롯을 업데이트하는 자동 재배치 기능이 있는 앱 - MATLAB & Simu

이 예제의 수정된 버전이 있습니다. 사용자가 편집한 내용을 반영하여 이 예제를 여시겠습니까?

kr.mathworks.com

 

 

핵심코드

 

1) Properties (Access = Private)

 

프로그램 코드 작성 시 사용할 변수 선언


    properties (Access = private)
        Data
        SelectedGenders
        SelectedColors
        BinWidth
        Histogram = gobjects(0) % 그래픽 객체(gobjects) 배열. 초기에는 비어있다는 의미.
        displayedIndices
    end

 

2) methods (Access = Private)

 

2-1) 히스토그램 작성 시 필요한 bin의 갯수를 정의하는 기능

        ( bin: 그래프의 가로 너비(width)를 의미 // 아래 사진에서 bin의 갯수는 6개)


        function NBins = numhistbins(app,data)
            binwidth = app.BinWidth;
            range2plot =  floor(min(data)) : binwidth : ceil(max(data));  % 데이터의 최솟값과 최댓값을 기반으로 빈(bin) 범위를 정의
            NBins = size(range2plot,2);  % 빈(bin)의 개수를 계산
        end 

 

2-2) Scatter(산점도) 그래프를 드러내고, HIstogram(히스토그램) 그래프를 숨기는 기능

 


        function annotateScatterPlot(app)
            % X라벨과 Y라벨의 업데이트
            app.UIAxes.XLabel.String = "Weight";
            app.UIAxes.YLabel.String = app.BloodPressureSwitch.Value; % Y축은 스위치 이름에 따라 변경됨
            % 히스토그램 슬라이더는 숨김처리
            app.BinWidthSliderLabel.Visible = "off";
            app.BinWidthSlider.Visible = "off";
        end

 

 

2-3) Histogram(히스토그램) 그래프를 드러내는 기능


        function annotateHistogram(app)
          % X라벨과 Y라벨의 업데이트
            app.UIAxes.XLabel.String = app.BloodPressureSwitch.Value;
            app.UIAxes.YLabel.String = "# of Patients";
           % 히스토그램 슬라이더 보임처리
            app.BinWidthSliderLabel.Visible = "on";
            app.BinWidthSlider.Visible = "on";
        end

 

2-4)  드롭다운 및 체크박스의 데이터들을 필터링하고 식별된 데이터들을 display하는 기능


        function filterData(app)
           % 필터링된 데이터의 인덱스를 추적하기 위한 임시 배열을 초기화하는 부분
            tempIndices = ones([size(app.Data,1),1]);
            
           % "Smoker" 컨트롤에 따라 데이터를 필터링하여 tempIndices 배열에 해당하는 열을 추가
            if app.NoCheckBox.Value && ~app.YesCheckBox.Value
                tempIndices = [tempIndices, app.Data.Smoker == 0]; % Smoker가 No일 시 tempIndices에 0을 추가
            elseif app.YesCheckBox.Value && ~app.NoCheckBox.Value
                tempIndices = [tempIndices, app.Data.Smoker == 1]; % Smoker가 Yes일 시 tempIndices에 1을 추가
            elseif  ~app.YesCheckBox.Value && ~app.NoCheckBox.Value
                tempIndices = [tempIndices, zeros([size(app.Data,1),1])]; % 둘 다 아니면, 영행렬을 추가
            end
            
           %  "Gender" 컨트롤에 따라 데이터를 필터링하여 tempIndices 배열에 해당하는 열을 추가
            if app.MaleCheckBox.Value && ~app.FemaleCheckBox.Value
                tempIndices = [tempIndices, app.Data.Gender == "Male"];
            elseif app.FemaleCheckBox.Value && ~app.MaleCheckBox.Value
                tempIndices = [tempIndices, app.Data.Gender == "Female"];
            elseif  ~app.FemaleCheckBox.Value && ~app.MaleCheckBox.Value
                tempIndices = [tempIndices, zeros([size(app.Data,1),1])];
            end
            
           %  "Location" 컨트롤에 따라 데이터를 필터링하여 tempIndices 배열에 해당하는 열을 추가
            if app.HospitalNameDropDown.Value ~= "All"
                tempIndices = [tempIndices, app.Data.Location == string(app.HospitalNameDropDown.Value)];
            end
            
            % 모든 조건을 만족하는 데이터를 display
            app.displayedIndices = (sum(tempIndices,2)/size(tempIndices,2) == 1);
        end

 

3) Callback Function

 

3-1) 앱이 시작될 때 데이터 로딩 및 초기화를 수행하는 기능


        function startupFcn(app)
            % 데이터 불러오기
            load("patients.mat","LastName","Gender","Smoker","Age","Height","Weight","Diastolic","Systolic","Location");
            
            % App의 탭에 따라 불러온 데이터를 table에 저장
            app.Data = table(LastName,Gender,Smoker,Age,Height,Weight,Diastolic,Systolic,Location);
            app.UITable.Data = app.Data;
            app.BinWidth = app.BinWidthSlider.Value;
            
            % 대응하는 데이터에 대해 축을 업데이트함
            updateSelectedGenders(app)
            refreshplot(app)
        end

 

3-2) 슬라이드 바를 조정해서 데이터를 변경하는 기능


        function SliderValueChanging(app, event)
            % Bin Width라는 슬라이드 바를 조절함
            app.BinWidth = event.Value;
            for ii=1:length(app.Histogram)
                app.Histogram(ii).NumBins = numhistbins(app,app.Histogram(ii).Data);
            end
        end

 

3-3) 그래프의 형태를 Scatter, Histogram으로 스위칭하는 기능


        function refreshplot(app, event)
            Genders = app.SelectedGenders;
            Colors = app.SelectedColors;
            
            % 새로운 플롯으로 시작함
            cla(app.UIAxes)
            hold(app.UIAxes,"on")
            app.Histogram = gobjects(0);
            
            % 데이터의 관련 세그멘트를 선택
            xdata = app.Data.Weight;
            ydata = app.Data.(app.BloodPressureSwitch.Value);
            
            % 컨트롤에 따른 데이터의 필터링
            filterData(app);
            
            % scatter나 histogram을 선택
            switch app.ButtonGroup.SelectedObject.Text
                
                case 'Scatter'
                    % 선택된 Gender에 따른 scatter를 그림
                    for ii = 1:length(Genders)
                        selectedpatients = ((app.Data.Gender == Genders(ii)) & (app.displayedIndices));
                        scatter(app.UIAxes, xdata(selectedpatients), ydata(selectedpatients), Colors{ii});
                    end
                    annotateScatterPlot(app)
                    
                case 'Histogram'
                    % 선택된 Gender에 따른 histogram을 그림
                    for ii = 1:length(Genders)
                        selectedpatients = ((app.Data.Gender == Genders(ii)) & (app.displayedIndices));
                        NBins = numhistbins(app,ydata(selectedpatients));
                        h = histogram(app.UIAxes, ydata(selectedpatients), NBins, "BinLimits", [floor(min(ydata)) ceil(max(ydata))]);
                        h.EdgeColor = Colors{ii};
                        h.FaceColor = Colors{ii};
                        app.Histogram = [app.Histogram h];
                    end
                    annotateHistogram(app)
                    
            end
            
            % 조건에 만족하는 데이터를 보여줌
            app.UITable.Data = app.Data(app.displayedIndices,:);
            drawnow;
        end

 

3-4) 성별과 흡연 여부에 따라 선택된 데이터를 업데이트 → UI 컴포넌트를 활성화/비활성화하는 기능


        function updateSelectedGenders(app, event)
            % Gender, Color, Smoker에 대해 빈 배열을 받음
            Genders = [ ] ;
            Colors = [ ] ;
            Smoker = [ ] ;
            
            if app.MaleCheckBox.Value % 남자를 선택하면 파란색
                Genders = "Male";
                Colors = "blue";
            end

            if app.FemaleCheckBox.Value % 여자를 선택하면 빨간색
                Genders = [Genders "Female"];
                Colors = [Colors "red"];
            end

            if app.YesCheckBox.Value % yes를 선택하면 흡연자
                Smoker = "Yes";
            end

            if app.NoCheckBox.Value % no를 선택하면 비흡연자
                Smoker = [Smoker "No"];
            end
            
            if isempty(Genders) || isempty(Smoker) % 만약 Gender와 Smoker가 모두 비어있다면
                app.BloodPressureSwitch.Enable = "off"; % Blood Pressure 스위치버튼을 막음
                app.ScatterButton.Enable = "off"; % Plotting Option 라디오버튼을 막음
                app.HistogramButton.Enable = "off";
                app.BinWidthSliderLabel.Enable = "off"; % Bin Width 슬라이드를 막음
                app.BinWidthSlider.Enable = "off";
            else
                app.BloodPressureSwitch.Enable = "on";
                app.ScatterButton.Enable = "on";
                app.HistogramButton.Enable = "on";
                app.BinWidthSliderLabel.Enable = "on";
                app.BinWidthSlider.Enable = "on";
            end
            app.SelectedGenders = Genders;
            app.SelectedColors = Colors;
            
            refreshplot(app)
        end