🌐 English|한국어

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.


[Unreleased]

Added

  • You can choose where Modan2 keeps your data. Preferences now has a Data folder row: point Modan2 at a larger drive, or anywhere else that suits you. The database, images, 3D models, backups and logs all move together — they are one library, and splitting them would leave either half useless on its own.

    Two things it deliberately does not do. It does not move your existing files — you keep them where they are until you move them yourself, and the dialog says so before you confirm. And it takes effect the next time you start Modan2, because the database is already open by the time you can change the setting. Leave it alone and everything works exactly as before.

    If a folder you chose is missing at startup (an external drive not plugged in, a network share that is down), Modan2 tells you which folder and asks what to do — quit, use the default, or start anyway — instead of quietly creating an empty library there, which looks the same as losing your data.

Fixed

  • Attached files could have been read from one folder and written to another. The storage location was resolved when the program started rather than when it was used, and inconsistently: attaching, replacing, duplicating and deleting files all ignored any change to it. Nothing was lost, because the location could not actually be changed before now — but it had to be fixed before it could be.

Changed

  • Log files are named Modan2_20260729.log instead of Modan2.20260729.log. Existing log files are left alone.

  • Preferences moved to your operating system’s settings folder%LOCALAPPDATA%\PaleoBytes\Modan2 on Windows, ~/Library/Application Support/PaleoBytes/Modan2 on macOS, ~/.config/PaleoBytes/Modan2 on Linux. They are settings the application can recreate, so they belong beside other applications’ settings rather than in with your datasets. Your existing preferences are copied over automatically on first launch; the old file is left alone and can be deleted.

    This also prepares for letting you choose where your data lives: a setting cannot be stored inside the folder it points at.

[0.2.0-beta.2] - 2026-07-28

A housekeeping beta. Nothing changes about morphometrics; what changes is where Modan2 puts things on your disk. The program used to write to four different places, two of them inside Roaming AppData — a share that follows your profile between machines on a managed network, and the wrong home for a 130 MB program folder or for scratch files. Everything you own now lives in one directory.

⚠️ Upgrading from 0.2.0-beta.1 or earlier (Windows)

The installer now performs a per-user install and identifies itself by a stable ID, so it no longer recognises installations made by earlier releases. It detects them and offers to remove the old version for you — accept, unless you have a reason to keep both.

Order matters if you decline. The Start Menu shortcut and the example datasets sit at fixed paths that both installations share, so uninstalling the old version after installing the new one takes them away from the new one too.

Your datasets, images and preferences are stored outside the program folder and are not affected either way.

Changed

  • Modan2 installs to %LOCALAPPDATA%\Programs instead of %APPDATA% (Roaming). The program folder is ~130 MB and was being synchronised with the user profile on domain-joined machines. %LOCALAPPDATA%\Programs is the standard location for an application installed for one user.

  • The installer no longer asks for administrator rights. It was requesting elevation for a per-user install; worse, consenting with a different administrator account installed Modan2 into that account’s folder, where the actual user could not see it.

  • Preferences moved to ~/PaleoBytes/Modan2/preferences.json, beside the database, media, logs and backups. One folder now holds everything you own, so backing up or moving an installation is a single directory copy. Preferences from the old location (~/.modan2/config.json) are copied over automatically on first launch; the old file is left untouched and can be deleted afterwards.

  • Temporary files also moved out of Roaming AppData into ~/PaleoBytes/Modan2/.

Fixed

  • --config read from one file and saved to another. Preferences changed during a session were written to the default location regardless of the path given on the command line.

  • The installer registers a publisher and an icon in Apps & features, both of which were blank.

[0.2.0-beta.1] - 2026-07-27

The 0.2 series moves to beta. Superimposition is now complete — all three methods work in 2D and 3D — and the documentation has been rebuilt against the application after a long stretch where the published site was out of date.

Added

  • Bookstein superimposition. Shapes are re-expressed as Bookstein shape coordinates by fixing the dataset’s baseline landmarks to a standard position (2D uses the baseline endpoints; 3D uses a 3-point baseline). Requires a baseline defined on the dataset.

  • Resistant Fit superimposition (RFTRA), in both 2D and 3D. It aligns using repeated medians of pairwise landmark relationships, so a few displaced landmarks do not drag the whole fit the way they can under Procrustes.

  • Missing landmarks are imputed for Bookstein and Resistant Fit too, using the same shape-fitting Procrustes already used.

  • A Quick Start page and a file format reference (TPS, NTS, Morphologika, X1Y1) in the manual, plus a glossary and a section on calibrating an object against a known distance.

Fixed

  • The superimposition method selector did nothing. Choosing Bookstein or Resistant Fit silently ran Procrustes. The options were disabled until the methods were implemented, and are now live.

  • NTS and X1Y1 files reported a landmark count of 0. The count is now computed correctly, and both parsers have test coverage.

  • Information and warning messages from a running analysis were dropped. They are shown in the status bar; errors still open a dialog.

  • A failed dataset-package import left files behind. The rollback now removes the media and directories it had created.

  • Two save actions could close their window on an error instead of reporting it (landmark names, preferences).

Changed

  • Coordinate values above 99999 are no longer clamped when a plot’s data range is computed.

  • Python 3.11 is no longer supported; 3.12 is the minimum.

Documentation

  • The documentation site had been stuck 411 commits behind — every docs build had failed since 2026-07-24 for two separate reasons. Fixed, and the site is current again.

  • The published manual was checked against the code, page by page. It documented a “Mark as Missing” flow that does not exist, environment variables and command-line flags the application never had, keyboard shortcuts that were never bound, and superimposition methods it does not offer. All corrected.

  • Installation instructions now match the actual release files — the version-stamped installer ZIP, DMG and AppImage — and say plainly that only the Windows build is well tested.

  • The Korean manual is complete. Every page is translated, using the application’s own Korean interface terms.

  • Documentation moved to docs/manual/, so what is published is unambiguous; docs/*.md is now repository-only developer notes.

Internal

  • Ruff gained PIE, RET, SIM, PERF, A and G, and cyclomatic complexity is now enforced as a ratchet. Adopting them surfaced several real defects, including a test that asserted nothing and a function that returned a dict or None depending on which branch it took.

[0.2.0-alpha.2] - 2026-07-24

A hardening release for the 0.2 alpha: several data-loss and crash fixes found by a file-I/O/security audit and by fuzzing, plus a large internal quality push (cross-platform CI, type checking, and a complexity-refactoring campaign).

Fixed

  • Semi-landmark curves are no longer lost on ZIP export/import. A dataset packaged to .zip and re-imported dropped its curve scheme and every traced curve; the package format now carries them (manifest schema 1.2, older packages still import).

  • Polygons are no longer dropped when importing a file. A Morphologika file with a [polygons] block imported with no polygons.

  • Missing landmarks survive ZIP round-trips correctly, stored with the app’s “Missing” marker instead of the string “None”.

  • NTS files now report the correct landmark count (it was always 0).

  • Korean (and other non-Latin) chart text renders instead of showing boxes, via a per-glyph font fallback built from the fonts installed on the machine.

  • Landmark file readers tolerate non-ASCII specimen names on any locale (e.g. cp949 files on a UTF-8 system and vice-versa), including a second set of readers the earlier fix had missed.

  • A malformed input file no longer crashes a reader — fuzzing surfaced a Morphologika crash on a bare [; parsers now fail with a clear error.

  • Data Exploration no longer crashes when an analysis has fewer components than the selected axis (a scatter plot with a 3rd axis on a 2-component PCA).

  • A requested CVA/MANOVA that fails is reported to you, instead of the analysis claiming success while silently saving nothing.

  • Saving an object is now atomic — a failure while attaching its image/3D model can no longer leave a half-written object.

  • More dialog actions surface errors instead of silently closing the window (expanded the guarded-slot coverage), with a global crash handler as a backstop.

  • Importing a crafted dataset package can no longer copy files from outside the package (path-traversal hardening).

Added

  • Export semi-landmark curves to TPS (CURVES=), symmetric to the existing import.

Changed / Internal

  • Cross-platform CI (Linux/Windows/macOS) with an import smoke test; linting, formatting, type-checking (mypy), a dependency CVE scan, and a coverage floor are now enforced.

  • A complexity-refactoring campaign brought the worst application function from a cyclomatic complexity of 56 down to 21, with characterization tests added for the viewers; this surfaced and fixed several of the bugs above.

  • Added docs/CODE_QUALITY_GUIDE.md.

[0.2.0-alpha.1] - 2026-07-23

Semi-landmark curves: trace a curve on a specimen and have it resampled into evenly-spaced semi-landmarks for analysis, with edge-snapping auto-detection. First alpha of the 0.2 series.

Added

  • Semi-landmark curves. Define curves for a dataset — how many semi-landmarks each carries — then trace them on each specimen. The traced curve is resampled into evenly-spaced points along its length, and analysis treats those points like ordinary landmarks. Fixed (anatomical) landmarks keep their positions and indices; the semi-landmarks follow after them. The raw trace is kept with the specimen, so you can re-trace or change the count at any time. A dataset can be analyzed with only semi-landmarks (no fixed landmarks) as well.

  • Snap to curve — edge auto-detection. While tracing, the curve snaps to the strongest image edge between your clicks (a “live-wire”), so a clean outline needs only a few clicks: start and end for a gentle curve, a couple of points in between for a sharp one. On by default in curve mode; uncheck Snap to curve for a plain hand trace. Enter accepts the trace, Esc cancels.

  • Smooth curve. Snapped traces are smoothed to remove the pixel staircase so the semi-landmarks sit on a clean curve, while the points you clicked stay put. Toggle it with the Smooth curve checkbox.

  • Edit a traced curve. Select a curve to adjust it — drag a point, click the line to add one, and right-click to delete a point or the whole curve (deleting a curve also works by right-clicking it in landmark mode). Snapped curves are edited by their clicked anchors and re-snap to the edge live as you drag. The selected curve is drawn thicker with square anchor handles.

  • Dataset-wide landmark names. Give each landmark a name/abbreviation and a description at the dataset level; the viewer shows the name instead of the index while digitizing, with the description as a tooltip.

  • “Show Expected” digitizing aid (2D). Once two landmarks are placed on a new specimen, the remaining positions are predicted from the dataset mean shape and shown as a guide so you know roughly where each one goes.

  • Import curves from TPS. CURVES= blocks in TPS files are read in as semi-landmark curves.

Changed

  • The dataset dialog is organized into tabs, and gains tables for dataset-wide landmark names and the curve scheme.

  • The object list shows an “LM Count” column and a “Curve” column, and refreshes on Save/Next/Previous while keeping your selection.

[0.1.12] - 2026-07-21

Legend arrangement in Data Exploration, a sharper 2D viewer, and a complete Korean interface.

Added

  • Arrange the legend in Data Exploration. With the legend shown, a Movable checkbox lets you drag it wherever it suits the plot, and Order… opens a list you can drag entries into the order you want (with A-Z / Z-A shortcuts). Entries used to appear in whatever order specimens happened to sit in the dataset. Both the order and the position are remembered per grouping variable and restored the next time you open the analysis.

Changed

  • The 2D viewer scales images more smoothly, so zooming and fitting no longer show the jagged edges that made fine detail harder to read while placing landmarks.

  • The Korean interface is fully translated. Strings added over several releases had never been picked up, so parts of the UI stayed in English — including some that had a translation but were being skipped when the translation file was built.

Fixed

  • A failure during startup now says what went wrong. The error was being reported behind the splash screen, which stays on top, so all you could see was a splash frozen on the step that failed. The splash now closes first and the message points at the log file.

  • --db now opens the database you name. The option was accepted and then ignored, so the default database was always used.

[0.1.8] - 2026-07-21

Better handling of large images, much more accurate missing-landmark estimation, and fixes for memory that was never released.

Added

  • Oversized images are downscaled when attached. Photos whose longer side exceeds 2560 px are stored as a smaller working copy (used for landmarking), while the pristine original is archived alongside it. Digitizing and viewing large photos is faster and lighter on memory, and no image data is lost.

  • “Show Original” checkbox in the object dialog. When an archived original exists, you can render the 2D view from the full-resolution image for extra detail while placing landmarks. This affects display only — landmark coordinates stay in the working-copy pixel space.

  • The About box links to the project page, so you can open it in your browser with a click.

Changed

  • Missing landmarks are estimated far more accurately. Both the “show estimate” preview and the estimation used in analysis now fit the mean shape onto the landmarks a specimen actually has — matching rotation, scale and position — before filling the gaps, and analysis repeats the estimate as the alignment settles. Estimates previously landed in the wrong place whenever a specimen was photographed at an angle; in analysis they were also computed before the specimens were aligned and then never revisited, so they were off by a large margin and that error fed into the results. On test shapes where the right answer is known, the error went from 61% of specimen size to essentially zero. Analysis results change for datasets with missing landmarks; datasets without them are unaffected.

Fixed

  • Zooming far into a 2D image no longer risks exhausting memory. The zoom scale is capped so the rendered image can always be allocated.

  • Dialogs are now released when closed. Every dialog that was opened stayed in memory for the rest of the session, so memory grew steadily as you worked — noticeably with the data exploration and analysis windows, which hold large plots. They are now freed on close.

  • Replacing an object’s image no longer leaves the old files behind. When the new image had a different file extension, the previous image (and its archived original) stayed on disk forever.

  • Deleting a dataset or an object now deletes its files too. Images, their archived originals and 3D models were left on disk indefinitely — for a dataset, its entire storage folder — so deleted data kept taking up space. Files already orphaned by earlier versions are not cleaned up automatically.

[0.1.7] - 2026-07-21

A small maintenance release: one crash fix and a 3D rendering speedup.

Changed

  • 3D landmark spheres render much faster. Spheres are now drawn from a sphere shape compiled once and reused, instead of being rebuilt triangle-by-triangle for every landmark on every frame. Rotating and dragging 3D views with many landmarks is noticeably smoother, especially in landmark-edit mode, which draws the scene twice.

Fixed

  • Chart no longer fails with “string index out of range” when the selected grouping variable is blank for some objects. Those objects now appear in the legend as an unlabeled group instead of breaking the plot.

[0.1.6] - 2026-07-20

Focused on making missing landmarks work end to end — from import, through editing and display, to analysis — and on the crashes found along the way.

Added

  • Missing landmark handling on import

    • Import detects the -999 morphometrics placeholder and asks whether to treat those coordinates as missing landmarks (defaults to yes)

    • “Always treat -999 as a missing landmark” checkbox remembers the answer

    • Correctly handles the invert-Y option, which negates a -999 in the Y column to +999 before the scan runs

  • Insert a missing landmark at a chosen position

    • “Add Missing” now inserts before the selected row instead of only appending, so a gap can be placed where it actually belongs

    • The button reads “Insert Missing” or “Add Missing” depending on whether a row is selected

  • Missing landmarks visible in the object list — the Landmarks column shows the recorded count with the missing tally beside it in red, e.g. 9 (1). The column still sorts numerically.

  • Italic legend labels — a grouping value wrapped in asterisks renders italic in plot legends, so taxon names typeset correctly (*Eurekia*Eurekia). Works for any script, including Hangul.

Changed

  • Landmark table cells are validated when an edit is committed. A cell accepts a number, or MISSING (a blank cell counts as missing); anything else reverts to the stored value with an explanatory tooltip. Previously any typo silently turned the landmark into a missing one.

  • Edits to the landmark table now update the viewer immediately rather than only at save time.

  • Analysis errors say what to do. A landmark-count mismatch names the object, both counts, and points at “Insert Missing”; a landmark missing in every object is named up front instead of failing deep inside PCA.

Fixed

  • Clearing a landmark cell no longer breaks the dataset. A blank tab/comma field produced a short landmark row, crashing count_landmarks, has_missing_landmarks and Procrustes superimposition with IndexError and taking the whole dataset’s analysis with it.

  • Clearing only the X coordinate no longer shifts Y into X’s slot — a silent coordinate corruption that produced no error at all.

  • Landmark-count consistency used two conflicting definitions, so an object with a missing landmark could be rejected against its own count while the Procrustes gate accepted the same dataset.

  • Analysis on a landmark missing in every object no longer fails with float() argument must be a string or a real number, not 'NoneType'.

  • Fixed a segmentation fault caused by item delegates being registered without a parent, leaving Qt holding a pointer to a garbage-collected object.

  • Fixed a circular import that broke import ModanComponents in a fresh interpreter.

Technical

  • Test suite grew from 1242 to 1404 passing (75 skipped)

  • New regression suites: import cycles (checked in a fresh subprocess, since in-process module caching hides them), landmark parsing, cell validation, sentinel import, count consistency, unimputable landmarks, count display

  • Single implementations for landmark counting (landmark_position_count, find_landmark_count_mismatch) shared by every gate that can reject a dataset

  • pre-commit installed and configured; AppDir/ excluded from the whitespace hooks, which corrupted git symlinks on filesystems without symlink support

  • Ruff pinned in .pre-commit-config.yaml to match the installed version

[0.1.5] - 2026-07-18

Stabilisation release. A full code review (R01) corrected several statistical results, a structural refactor removed the last god-methods and dead modules, and an error-handling audit closed the paths where a failure could kill a window silently.

Note for existing analyses: the CVA and MANOVA fixes below change numeric output. Analyses saved before 0.1.5 may differ if re-run.

Added

  • Data Exploration plot

    • Optional data-point labels

    • Snap-to-point when picking shapes

    • Shape-preview snapping is now toggleable (“Snap to points”)

  • Object editing — landmark mode is entered automatically after calibration, and exactly one tool mode stays selected

Fixed

  • Statistics correctness

    • CVA: use pseudo-inverse for a singular within-group covariance matrix instead of failing or producing garbage

    • CVA: raw eigenvalues no longer overwritten by their percentages

    • CVA/MANOVA: the Z coordinate of 3D landmarks is no longer dropped when flattening shapes

    • MANOVA: variable truncation is surfaced instead of silently capping

  • Crashes and silent failures

    • Clicking the dataset tree and exporting an analysis to Excel could kill the window with no message; the export crash was traced to the Shapes sheet

    • Frozen (packaged) builds failed at startup with “Can’t determine version for pytz”

    • Preferences were intermittently reset — settings are now written atomically

    • Error-handling audit: 40+ user-triggered handlers across the main window, dialogs, file parsers, 3D model I/O and zip import now report failures instead of dying quietly

  • Data integrity

    • Multi-row database operations are wrapped in transactions, so a failure part-way through no longer leaves a half-written dataset

    • Corrected model field names in controller create/import paths

    • Class-level mutable attributes were shared between instances

    • Analysis results were silently not persisted when the analysis type was passed in lowercase

  • Interface

    • The Preferences dialog is scrollable, so it is usable on low-resolution monitors

Changed

  • Performance — eliminated N+1 queries in CVA/MANOVA group extraction and in dataset switching; vectorised average-shape and CVA covariance computation

Technical

  • Removed dead code: ModanDialogs.py (2,539 lines) migrated to the dialogs/ package, plus 6 unused modules and 8 stale build specs

  • De-duplicated the MODE dictionary (15 copies → 1) and object-viewer constants into MdConstants

  • Decomposed god-methods: run_analysis, prepare_scatter_data, read_settings, and two dialog __init__s; moved dialog database/file I/O into ModanController

  • Added the guard_slot decorator for Qt signal handlers

  • Repo-wide ruff lint/format clean; numpy pins reconciled to >=2.0.0,<3.0.0

  • CI: build numbers derived from commit count across all build workflows; Inno Setup pinned to 6.7.3

[0.1.5-beta.2] - 2025-11-03

Added

  • Object Preview Enhancements

    • Preview toolbar button icon (icons/Preview.png)

    • Smart button activation (enabled only when dataset is selected)

    • Consistent UI behavior with other dataset-related actions

Changed

  • UI Consistency Improvements

    • Preview button now follows same activation pattern as New Object, Export, and Analyze buttons

    • Preview button disabled when analysis is selected or no dataset loaded

    • Improved visual feedback with proper icon display

Fixed

  • Object Drag and Drop

    • Fixed NameError: name 'CustomDrag' is not defined when dragging objects between datasets

    • Added missing CustomDrag import in components/widgets/table_view.py

    • Fixed cursor not restoring to normal after drag operation completes

    • Implemented proper cursor stack cleanup using QApplication.restoreOverrideCursor()

    • Cursor now correctly reverts to arrow cursor after both successful and cancelled drag operations

Technical

  • Code Quality

    • Added cursor restoration in both startDrag() and mouseReleaseEvent() methods

    • Used while loop to clear all override cursors from Qt’s cursor stack

    • Improved drag operation robustness with proper cleanup

    • All drag widget tests passing (3/3)

    • Overall test coverage maintained at 99.6% (230/231 tests passing)

[0.1.5-beta.1] - 2025-10-08

Added (Phase 7 - Performance Testing & Scalability)

  • Comprehensive Performance Testing Infrastructure

    • Large-scale benchmarking tool (scripts/benchmark_large_scale.py)

    • CVA performance profiler (scripts/profile_cva.py)

    • Memory profiling system (scripts/profile_memory.py)

    • UI responsiveness tests (scripts/test_ui_responsiveness.py)

  • Performance Validation (All Targets Exceeded)

    • Load performance: 18-200× better than targets

      • 1000 objects load: 277ms (target: < 5s) - 18× faster

      • 1000 objects PCA: 60ms (target: < 2s) - 33× faster

    • Memory efficiency: 125× better than target

      • 1000 objects: 4.04MB peak (target: < 500MB)

      • Linear scaling: ~4KB per object

      • No memory leaks detected (2.7KB growth over 50 iterations)

    • UI responsiveness: 9-5091× better than targets

      • Widget creation: 12.63ms for 1000-row table (target: < 100ms) - 8× faster

      • Dataset loading: 536ms for 1000 objects (target: < 5s) - 9× faster

      • Progress updates: 152,746/sec (target: > 30/sec) - 5091× faster

  • Comprehensive User Documentation

    • Quick Start Guide (10-minute tutorial)

    • Complete User Guide (400+ lines covering all features)

    • Performance guide integrated with Phase 7 results

    • Troubleshooting section with solutions

    • Installation guide for all platforms

    • Build guide for developers

  • Release Preparation (Phase 8)

    • BUILD_GUIDE.md - Comprehensive build instructions

    • INSTALL.md - Platform-specific installation guides

    • Enhanced documentation structure

Changed

  • Code Quality Improvements

    • Extensive test coverage (1,240 tests, 93.5% pass rate)

    • Integration testing complete (Phase 6)

    • Component testing complete (Phase 5)

    • Performance profiling and validation (Phase 7)

Performance

  • Validated Scalability

    • Tested up to 2,000 objects

    • All operations linear O(n) scaling

    • Production-ready for datasets of 100,000+ objects

Documentation

  • Complete Documentation Suite

    • User documentation for all skill levels

    • Developer guides and API references

    • Build and installation instructions

    • Performance expectations and best practices


[0.1.5-alpha.1] - 2025-09-11

Added

  • JSON+ZIP 데이터셋 패키징 시스템

    • 완전한 데이터셋 백업 및 공유를 위한 새로운 export/import 형식

    • JSON schema v1.1 with 확장된 메타데이터 (wireframe, polygons, baseline, variables)

    • ZIP 패키징으로 이미지 및 3D 모델 파일 포함 지원

    • 구조화된 파일 레이아웃 (dataset.json, images/, models/)

    • 손실 없는 라운드트립 데이터 보존

  • 보안 및 안정성 기능

    • Zip Slip 공격 방어 시스템

    • 트랜잭션 기반 import (실패 시 자동 롤백)

    • 파일 무결성 검증 (MD5 체크섬)

    • 안전한 ZIP 압축 해제 (safe_extract_zip())

    • JSON 스키마 검증 및 에러 리포팅

  • 새로운 API 함수들 (MdUtils.py)

    • serialize_dataset_to_json() - 데이터셋을 JSON 구조로 직렬화

    • create_zip_package() - 파일 수집 및 ZIP 패키징

    • import_dataset_from_zip() - 안전한 ZIP 기반 데이터셋 import

    • collect_dataset_files() - 데이터셋 관련 파일 경로 수집

    • estimate_package_size() - 패키지 크기 추정

    • validate_json_schema() - JSON 스키마 유효성 검사

  • 사용자 인터페이스 개선

    • Export Dialog에 “JSON+ZIP Package” 옵션 추가

    • “Include image and model files” 토글 기능

    • 실시간 파일 크기 추정 표시

    • Import Dialog에 JSON+ZIP 형식 지원 추가

    • 진행률 추적 및 진행 상황 콜백

Changed

  • 기존 export 형식 유지

    • TPS, NTS, Morphologika, CSV/Excel 형식 계속 지원

    • JSON+ZIP은 완전한 백업용 추가 옵션으로 제공

  • 파일 명명 규칙 개선

    • ZIP 내부 파일은 <object_id>.<ext> 형식으로 충돌 방지

    • 상대 경로 사용으로 플랫폼 독립성 확보

  • 데이터베이스 처리 개선

    • 중복 데이터셋 이름 자동 해결 (“Dataset (1)”, “Dataset (2)” 등)

    • 변수 매핑 및 랜드마크 처리 최적화

Fixed

  • 크로스 플랫폼 호환성

    • UTF-8 인코딩으로 한국어 파일명 지원

    • Windows, macOS, Linux 경로 처리 통일

    • 파일 시스템 안전성 검증 추가

  • 메모리 및 성능 최적화

    • 대용량 파일 스트리밍 처리

    • 임시 파일 안전한 정리 (context manager 사용)

    • 에러 발생 시 부분 import 방지

[0.1.4] - 2025-09-10

Added

  • CI/CD 및 빌드 시스템

    • GitHub Actions 워크플로우 구축 (자동 빌드, 테스트, 릴리즈)

    • 크로스 플랫폼 빌드 지원 (Windows, Linux, macOS)

    • PyInstaller 기반 자동화 빌드 스크립트 (build.py)

    • 빌드 번호 시스템 및 버전 관리 중앙화 (version.py)

  • 테스트 인프라

    • pytest 기반 자동화 테스트 시스템 (229개 테스트, 13개 모듈)

    • 테스트 카테고리: 단위, 통합, 성능, GUI, 워크플로우

    • CI 통합으로 PR시 자동 테스트 실행

    • 테스트 커버리지 분석 도구 설정

  • UI/UX 기능

    • 오버레이 드래그 및 코너 스냅 기능

    • 오버레이 타이틀 표시

    • 스플래시 스크린 (빌드 정보 및 저작권 표시)

    • 3D 랜드마크 인덱스 표시 복원 (GLUT 사용)

    • 툴바 버튼 상태 관리 개선

    • TreeView 사용성 개선

    • 읽기 전용 열 컨텍스트 메뉴

  • 문서화

    • 한국어 README (README.ko.md)

    • 개발 가이드 문서 (CLAUDE.md, GEMINI.md)

    • 릴리즈 가이드 및 버전 관리 문서

    • Windows Defender 공지 문서

    • 상세한 개발 로그 (devlog 디렉토리)

  • 국제화 (i18n)

    • 한국어 번역 대폭 개선

    • 언어 설정 즉시 적용 기능

    • 번역 파일 업데이트 (Modan2_ko.ts)

  • 코드 인덱싱 시스템

    • 소스코드 구조 분석 및 인덱싱 도구 구축

    • 대화형 HTML 대시보드 (tools/visualize_index.py)

    • 심볼 검색 및 의존성 분석 도구

Changed

  • 코드 구조 개선

    • 새로운 모듈 분리: ModanController.py, MdHelpers.py, MdConstants.py, ModanWidgets.py

    • 설정 관리를 QSettings에서 JSON으로 마이그레이션

    • 로깅 시스템 전환 (print문을 logging 모듈로)

    • 에러 핸들링 강화 (체계적인 try-catch 구조)

    • 저작권 정보 동적 연도 업데이트

  • 의존성 업데이트

    • NumPy 2.0+ 지원 (OpenGL 호환성 문제 해결)

    • Python 3.12 지원

    • 요구사항 파일 정리 및 크로스 플랫폼 지원

  • 데이터 분석 개선

    • PCA/CVA 분석 시스템 재구조화

    • 회귀 분석과 산점도 분리

    • Data Exploration Dialog 재구성

    • 속성(property)에서 변수(variable)로 용어 통일

Fixed

  • 분석 기능 개선

    • CVA/MANOVA 변수 선택 오류 수정: 선택된 그룹화 변수가 분석 함수에 제대로 전달되지 않던 심각한 문제 해결

    • 분석 정확도 향상: CVA 및 MANOVA 계산에 올바른 범주형 변수가 사용되도록 변수 인덱싱 수정

    • 데이터 검증 강화: 분석 실행 전 그룹화 변수 요구사항에 대한 적절한 검사 추가

  • 주요 버그 수정

    • PCA 분석 일관성 및 차원 문제 해결

    • Reset Pose 기능 완전 복구

    • Windows Defender 오탐 문제 완화

    • OpenGL/GLUT와 matplotlib 호환성 문제 해결

    • Linux/WSL Qt 플랫폼 플러그인 오류 수정

    • CI/CD 테스트 XIO fatal 오류 해결

    • 썸네일 동기화 문제 (WSL 특정)

    • landmark_count 의존성 제거 및 동적 계산

    • 2D 객체 뷰 마이너 버그 수정

    • 데이터셋 저장 모니터링 코드 개선

    • shape retrieval 문제 해결 (currentData vs currentIndex)

    • 와이어프레임 랜드마크 인덱스 불일치 수정

  • 빌드 및 배포

    • InnoSetup 출력 디렉토리 수정

    • Linux AppImage 생성 프로세스 개선

    • macOS 빌드 아티팩트 패턴 수정

    • Anaconda Python 호환성 개선

  • 테스트 수정

    • PyQt5 호환성 문제 해결

    • 테스트 데이터에 그룹화 변수 추가

Removed

  • 하드코딩된 Modan2.spec 파일 (동적 생성으로 전환)

  • 레거시 테스트 스크립트 (pytest로 마이그레이션)

[0.1.3] - 2024-06-21

Added

  • 초기 안정 버전 릴리즈

  • 기본 형태 분석 기능

  • 2D/3D 랜드마크 지원

  • TPS, NTS, OBJ, PLY, STL 파일 형식 지원

  • 기본 통계 분석 기능 (PCA, CVA, MANOVA)

[0.1.2] - 2024-05-30

Added

  • 3D 모델 지원 (OBJ, PLY, STL)

  • 2D/3D 뷰어 개선

  • 데이터셋 계층 구조

[0.1.1] - 2024-04-12

Added

  • 기본 형태측정 분석

  • 프로크루스테스 중첩정렬

  • 간단한 데이터 관리

[0.1.0] - 2024-03-01

Added

  • 초기 개발 버전

  • 개념 증명(proof of concept)