From 15dd72f8e3b6bdc4f79323beb55fb13da3c22a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johana=20Sup=C3=ADkov=C3=A1?= Date: Fri, 2 Apr 2021 15:38:31 +0200 Subject: [PATCH] Separating tracks by phase - Readme updates - Corrected credits - Tracks are separated when phase value drops - Statistics mirrors age correctly --- Manual.md | 22 ++++---- README.md | 33 ++++++++++- pom.xml | 6 ++ src/main/java/GUI/TextOnly.java | 2 +- src/main/java/backend/Data.java | 6 +- src/main/java/backend/Statistics.java | 12 +++- src/main/java/backend/TableModel.java | 2 +- src/main/resources/GUI/FXMLTableView.fxml | 6 +- src/main/resources/Readme.txt | 23 ++++---- src/test/backend/DataTest.java | 68 ----------------------- 10 files changed, 76 insertions(+), 104 deletions(-) delete mode 100644 src/test/backend/DataTest.java diff --git a/Manual.md b/Manual.md index 1fbc754..6066bcc 100644 --- a/Manual.md +++ b/Manual.md @@ -18,7 +18,7 @@ Use one of the following ways of inputting the data: - **Fill in the form** on the right. - Upload **data file** via menu Data > Upload input data file. -The uncertainty is computed using 1000 estimations following the Monte Carlo simulations. +The uncertainty is computed from the Monte Carlo simulation on a thousand of points with a normal distribution. To turn off computing the uncertainty and speed the estimation up, uncheck the Compute uncertainty option. Uncertainty that is equal to 0 is overwritten to uncertainty coming from points in evolutionary line. @@ -43,15 +43,15 @@ will be set to 0. ### Grid (models) To upload custom grid, navigate to menu Grid > Upload new grid. Any header lines need to start with '#' sign to be parsed correctly. -Grid data need to be grouped by initial mass and sorted by evolutionary -phase. The GUI shows only a part of the grid data, +Grid data need to be a) labeled (isochrones) or b) grouped by initial mass and +sorted by evolutionary phase (evolutionary tracks). The GUI shows only a part of the grid data, but all points are taken into account when computing. Accepted format is a .txt file. Use space or ',' delimiter between attributes. To obtain correct uncertainty results, please follow the results table's header for specification of values representation: -#Teff[lg K] | Lum[lg Lsun] | Age[dex yrs] | Rad[Rsun] | Mass[Msun] | Phase +#lgTeff[K] | lgLum[Lsun] | lgAge[yrs] | Rad[Rsun] | Mass[Msun] | Phase --- | --- | --- | --- |--- |--- 3.66943 | -0.72127 | 8.23306 | 0.66695 | 0.75000 | 5.00000 3.66932 | -0.72112 | 8.26683 | 0.66741 | 0.75000 | 5.00053 @@ -59,10 +59,11 @@ for specification of values representation: 3.66912 | -0.72077 | 8.33767 | 0.66828 | 0.75000 | 5.00179 ... and more -if tracks' labels are missing, mass delimiter (0.01) is applied to separate tracks. +if tracks' labels are missing, points are separated into tracks when the value of phase drops +(as the data should be sorted by phase within tracks). If labels are provided: -#Teff[lg K] | Lum[lg Lsun] | Age[dex yrs] | Rad[Rsun] | Mass[Msun] | Phase | Label +#lgTeff[K] | lgLum[Lsun] | lgAge[yrs] | Rad[Rsun] | Mass[Msun] | Phase | Label --- | --- | --- | --- |--- |--- |--- 3.66943 | -0.72127 | 8.23306 | 0.66695 | 0.75000 | 5.00000 | 1 3.66932 | -0.72112 | 8.26683 | 0.66741 | 0.75000 | 5.00053 | 1 @@ -70,17 +71,16 @@ If labels are provided: 3.66912 | -0.72077 | 8.33767 | 0.66828 | 0.75000 | 5.00179 | 1 ... and more -points with the same label (in a continuous block of data) create a track. +points with the same label (in a continuous block of data) create a track. This way isochrones can be loaded. -Default grid data is extracted from [CMD web interface](http://stev.oapd.inaf.it/cgi-bin/cmd). -Credit: PARSEC and COLIBRI tracks (Marigo et al. (2017)). +Default grid data is extracted from [PARSEC STELLAR EVOLUTION CODE](https://people.sissa.it/~sbressan/parsec.html). -The **phase labels** in the default grid file are described [here](https://people.sissa.it/~sbressan/CAF09_V1.2S_M36_LT/readme.txt), StIFT uses these: +The **phase labels** in the default grid file are described [here](https://people.sissa.it/~sbressan/CAF09_V1.2S_M36_LT/readme.txt), the default grid in the StIFT uses these: #Value | Phase | Description --- | --- | --- 4 | NEAR_ZAM | This point is very near the ZAMS 5 | MS_BEG | H burning fully active -6 | POINT_B | Almost end of the H burning. Small contraction phase begins here for interm. & massive stars +6 | POINT_B | Almost end of the H burning. Small contraction phase begins here for interm. & massive stars 7 | POINT_C | Small contraction ends here and star move toward RG 8 | RG_BASE | RG base 9 | RG_BMP1 | RGB bump in Low Mass Stars (marked also for other masses) diff --git a/README.md b/README.md index e81b507..701c599 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,35 @@ In target folder run with `java -jar stift-1.0-SNAPSHOT.jar` or open the .jar fi This app is the topic of my bachelor's thesis at FI MUNI. It should be useful to astrophysicists as some stellar characteristics cannot be directly observed and need to be estimated from known data. The process of estimation is called isochrone fitting and is step by step described in > MALKOV, O. Yu.; SICHEVSKIJ, S. G.; KOVALEVA, D. A.: "Parametrization of single and binary stars", Monthly Notices of the Royal Astronomical Society. (2009), vol. 401, no. 1: 695. https://doi.org/10.1111/j.1365-2966.2009.15696.x -The grid data is grouped by mass and sorted by evolutionary status (phase). The default grid data is extracted from [CMD web interface](http://stev.oapd.inaf.it/cgi-bin/cmd) containing -PARSEC and COLIBRI tracks (Marigo et al. (2017)). +Evolutionary tracks or isochrones can be imported as the grid data. The default grid data is extracted from [PARSEC STELLAR EVOLUTION CODE](https://people.sissa.it/~sbressan/parsec.html): +> BRESSAN, A. et al: "PARSEC: stellar tracks and isochrones with the PAdova and TRieste Stellar Evolution Code", Monthly Notices of the Royal Astronomical Society. (2012), vol. 427, no. 1: 127. https://doi.org/10.1111/j.1365-2966.2012.21948.x + After the input is entered, four neighbours are found in the grid data and interpolated for line points estimation. Line points are then interpolated for final result estimation. The uncertainty is computed from the Monte Carlo simulation on a thousand of points with a normal distribution. + +## Thanks +My thanks go to Ernst Paunzen for the insight and consultations and to Martin Kuba for technical advice and supervision. + +## License + +MIT License + +Copyright (c) 2021 Johana Supíková + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/pom.xml b/pom.xml index ef92669..a5131ce 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,12 @@ ${javafx.version} mac + + junit + junit + RELEASE + test + diff --git a/src/main/java/GUI/TextOnly.java b/src/main/java/GUI/TextOnly.java index 6a8889f..21503b2 100644 --- a/src/main/java/GUI/TextOnly.java +++ b/src/main/java/GUI/TextOnly.java @@ -60,7 +60,7 @@ public static void main(String[] args) { System.out.printf("Input:%n%.4f\t%.4f uncertainties: %.4f\t%.4f%n", x, y, x_unc, y_unc); ComputationStats stats = data.estimateStats(x, y, x_unc, y_unc, rounding); System.out.println("Estimation method: " + stats.getResult().getResultType()); - System.out.println("Teff[lg] Lum[lg] Age[dex] Rad Mass Phase"); + System.out.println("lgTeff[K] lgL[Lsun] lgAge[yrs] Rad[Rsun] Mass[Msun] Phase"); if (stats.getStar11() != null || stats.getStar12() != null || stats.getStar21() != null || stats.getStar22() != null) { System.out.println("Neighbours:"); diff --git a/src/main/java/backend/Data.java b/src/main/java/backend/Data.java index ae8fb3b..b123d0c 100644 --- a/src/main/java/backend/Data.java +++ b/src/main/java/backend/Data.java @@ -15,7 +15,6 @@ public class Data { private final ArrayList> groupedData; private ArrayList currentGroup; - public static double TRACKS_DELIMITER = 0.01; private final HashSet currentPhases; private int currentLabel = 0; private final ZAMS zams = new ZAMS(); @@ -30,9 +29,8 @@ public Data() { * Add star to relevant group * @param star New star */ - public void addStar(Star star){ - if (!currentGroup.isEmpty() && Math.abs(currentGroup.get(currentGroup.size() - 1).getMass() - star.getMass()) - > TRACKS_DELIMITER) { + public void addStar(Star star){ + if (!currentGroup.isEmpty() && currentGroup.get(currentGroup.size() - 1).getPhase() > star.getPhase()) { addCurrentGroupToGroupedData(); currentGroup = new ArrayList<>(); } diff --git a/src/main/java/backend/Statistics.java b/src/main/java/backend/Statistics.java index 77f7529..3fafdc9 100644 --- a/src/main/java/backend/Statistics.java +++ b/src/main/java/backend/Statistics.java @@ -92,12 +92,20 @@ public static void computeUncertainty(ComputationStats stats) { return; } - if (statistics[0].getN() < (N * 0.95)) { //more than 5% points are not estimated - for (int i = 2; i < 6; i++) { + if (statistics[0].getN() < (N * 0.95)) { //more than 5% points are not estimated -> mirror uncertainties + for (int i = 3; i < 6; i++) { Double[] uncertainty = result.getUncertainty(i); double maxUncertainty = Math.max(Math.abs(uncertainty[0]), Math.abs(uncertainty[1])); result.setUncertainty(i, -maxUncertainty, maxUncertainty); } + //special handling for age + Double[] ageUncertainty = result.getUncertainty(2); + double ageAbsUncertainty = Math.max( + Math.abs(UnitsConverter.fromDex(result.getAge() + ageUncertainty[0]) - UnitsConverter.fromDex(result.getAge())), + Math.abs(UnitsConverter.fromDex(result.getAge() + ageUncertainty[1]) - UnitsConverter.fromDex(result.getAge()))); + double agePositiveError = UnitsConverter.toDex(UnitsConverter.fromDex(result.getAge()) + ageAbsUncertainty) - result.getAge(); + double ageNegativeError = UnitsConverter.toDex(UnitsConverter.fromDex(result.getAge()) - ageAbsUncertainty) - result.getAge(); + result.setUncertainty(2, ageNegativeError, agePositiveError); } fixToZero(result); diff --git a/src/main/java/backend/TableModel.java b/src/main/java/backend/TableModel.java index cdb8dc5..a2e5660 100644 --- a/src/main/java/backend/TableModel.java +++ b/src/main/java/backend/TableModel.java @@ -41,7 +41,7 @@ public synchronized void addResult(ResultStar newResult) { */ public void exportResults(File file) throws IOException { FileWriter fileWriter = new FileWriter(file); - fileWriter.write("#Teff[lgK] e_lgTeff L[lgLsun] e_lgL Age[dexYrs] e_dexAge e_dexAge R[Rsun] e_R e_R M[Msun] e_M e_M Phase e_Phase e_Phase estType" + System.getProperty("line.separator")); + fileWriter.write("#lgTeff[K] lgTeff lgL[Lsun] e_lgL lgAge[yrs] e_lgAge e_lgAge R[Rsun] e_R e_R M[Msun] e_M e_M Phase e_Phase e_Phase estType" + System.getProperty("line.separator")); for (ResultStar result : filteredList) { fileWriter.write(String.format("%s %s %s %s %s %s %s" + System.getProperty("line.separator"), result.getFormattedTemperature(), result.getFormattedLuminosity(), result.getFormattedAge(), diff --git a/src/main/resources/GUI/FXMLTableView.fxml b/src/main/resources/GUI/FXMLTableView.fxml index c8a1681..e00c067 100644 --- a/src/main/resources/GUI/FXMLTableView.fxml +++ b/src/main/resources/GUI/FXMLTableView.fxml @@ -6,9 +6,9 @@ - - - + + + diff --git a/src/main/resources/Readme.txt b/src/main/resources/Readme.txt index aaa28a3..1e04a9c 100644 --- a/src/main/resources/Readme.txt +++ b/src/main/resources/Readme.txt @@ -8,49 +8,48 @@ please contact me at xsupikov@fi.muni.cz. Any feedback is highly appreciated. ============================== -Default grid data is extracted from http://stev.oapd.inaf.it/cgi-bin/cmd. -PARSEC and COLIBRI tracks Marigo et al. (2017). +The default grid data is extracted from PARSEC STELLAR EVOLUTION CODE: +https://people.sissa.it/~sbressan/parsec.html StIFT finds 4 neighbours for input coordinates, interpolates to create line points and interpolates again to obtain result estimation. -The method is described by Malkov et al. (2010) +The method is described by Malkov et al. (2010): https://doi.org/10.1111/j.1365-2966.2009.15696.x -The uncertainty is computed using 1000 estimations -following the Monte Carlo simulations, used also by -S. G. Sichevskij (2017): -https://doi.org/10.1134/S1063772917030076 +The uncertainty is computed from the Monte Carlo simulation on a thousand of points with a normal distribution. + To turn off computing the uncertainty and speed the estimation up, uncheck the Compute uncertainty option. Uncertainty that is equal to 0 is overwritten to uncertainty coming from points in evolutionary line. To upload custom grid, choose Grid > Upload new grid. Any header lines need to start with '#' sign to be parsed correctly. -Grid data need to be grouped by initial mass and -sorted by evolutionary phase. The GUI shows only +Grid data need to be a) labeled (isochrones) or b) grouped by initial mass and +sorted by evolutionary phase (evolutionary tracks). The GUI shows only a part of the grid data, but all points are taken into account when computing. Accepted format is a .txt file. Use space or ',' delimiter between attributes. To obtain correct uncertainty results, please follow the results table's header for specification of values representation: -#Teff[lg K] Lum[lg Lsun] Age[dex yrs] Rad[Rsun] Mass[Msun] Phase +#lgTeff[K] lgL[Lsun] lgAge[yrs] Rad[Rsun] Mass[Msun] Phase 3.66943 -0.72127 8.23306 10.66660 0.75000 5.00000 3.66932 -0.72112 8.26683 10.66690 0.75000 5.00053 3.66922 -0.72095 8.30172 10.66718 0.75000 5.00112 3.66912 -0.72077 8.33767 10.66747 0.75000 5.00179 ... or -#Teff[lg K] Lum[lg Lsun] Age[dex yrs] Rad[Rsun] Mass[Msun] Phase Label +#lgTeff[K] lgL[Lsun] lgAge[yrs] Rad[Rsun] Mass[Msun] Phase Label 3.66943 -0.72127 8.23306 10.66660 0.75000 5.00000 1 3.66932 -0.72112 8.26683 10.66690 0.75000 5.00053 1 3.66922 -0.72095 8.30172 10.66718 0.75000 5.00112 1 3.66912 -0.72077 8.33767 10.66747 0.75000 5.00179 1 ... to specify how points should be separated into tracks - if no label -is provided to identify tracks, tracks are separated by mass delimiter (0.01). +is provided, points are separated into tracks when the value of phase +drops (as the data should be sorted by phase within tracks). To upload input data, choose Data > Upload input data file. Provide a .txt file and comment out header lines with '#' symbol: diff --git a/src/test/backend/DataTest.java b/src/test/backend/DataTest.java deleted file mode 100644 index 05161f9..0000000 --- a/src/test/backend/DataTest.java +++ /dev/null @@ -1,68 +0,0 @@ - -package backend; - -import org.junit.Assert; -import static org.junit.Assert.assertEquals; -import org.junit.Test; - -/** - * Test cases for Data class - */ -public class DataTest { - - /** - * Test of addStar method, of class Data. - */ - @Test - public void testAddStar() { - System.out.println("addStar"); - Data simpleData = new Data(); - Star star5 = new Star(1.6, 5.0, 3.0, 4.0, 5.0, 6.0); - simpleData.addStar(star5); - assert(simpleData.getGroupedData().get(5.0).size() == 1); - assertEquals(simpleData.getGroupedData().get(5.0).get(0), star5); - } - - /** - * Test of intersection method, of class Data. - */ - @Test - public void testIntersection() { - System.out.println("intersection"); - Data simpleData = new Data(); - Star star1 = new Star(1.0, 0.7, 3.0, 4.0, 1.0, 6.0); - Star star3 = new Star(2.0, 0.8, 3.0, 4.0, 1.0, 6.0); - simpleData.addStar(star1); - simpleData.addStar(star3); - double[] expectedResult = {1.5, 0.75}; - Assert.assertArrayEquals(expectedResult, simpleData.intersection(star1, star3, 1.5, 0.0), 0.00001); - double[] expectedResult2 = {1.0, 0.7}; - Assert.assertArrayEquals(expectedResult2, simpleData.intersection(star1, star3, 1.0, 20.0), 0.00001); - } - - /** - * Test of findNearestStars method, of class Data. - */ - @Test - public void testFindNearestStars() { - System.out.println("findNearestStars"); - Data simpleData = new Data(); - Star star1 = new Star(1.0, 0.7, 3.0, 4.0, 1.0, 6.0); - Star star2 = new Star(1.5, 4.0, 3.0, 4.0, 3.0, 6.0); - Star star3 = new Star(2.0, 0.8, 3.0, 4.0, 1.0, 6.0); - Star star4 = new Star(2.5, 4.2, 3.0, 4.0, 3.0, 6.0); - simpleData.addStar(star1); - simpleData.addStar(star2); - simpleData.addStar(star3); - simpleData.addStar(star4); - Star[] expectedResult = {star2, star4, star3, star1}; - Assert.assertArrayEquals(expectedResult, simpleData.findNearestStars(1.7, 2.0)); - Star star5 = new Star(3.0, 0.9, 3.0, 4.0, 1.0, 6.0); - Star star6 = new Star(3.5, 4.24, 3.0, 4.0, 3.0, 6.0); - simpleData.addStar(star5); - simpleData.addStar(star6); - Assert.assertArrayEquals(expectedResult, simpleData.findNearestStars(1.7, 2.0)); - Star[] expectedResult2 = {star4, star6, star5, star3}; - Assert.assertArrayEquals(expectedResult2, simpleData.findNearestStars(2.99, 4.205)); - } -}