├── LICENSE ├── README.md ├── gui ├── __init__.py ├── configurespots_widget.py ├── conjunction_widget.py ├── curveproperties_dialog.py ├── dc_widget.py ├── dimensions_widget.py ├── eclipsetimings_widget.py ├── history_widget.py ├── lcdcpicker_dialog.py ├── lineprofile_widget.py ├── loadobservations_widget.py ├── mainwindow_widget.py ├── oc_widget.py ├── outputview_widget.py ├── single_conjunction.py ├── starpositions_widget.py └── syntheticcurve_widget.py ├── pywd2015.py ├── resources ├── PTM55FT-OFL.txt ├── PTM55FT.ttf ├── configurespots_widget.ui ├── conjunction_widget.ui ├── curveproperties_dialog.ui ├── dc_widget.ui ├── dimensions_widget.ui ├── eclipsetimings_widget.ui ├── history_widget.ui ├── lcdcpicker_dialog.ui ├── lineprofile_widget.ui ├── loadobservations_widget.ui ├── mainwindow_widget.ui ├── next.png ├── oc_widget.ui ├── outputview_widget.ui ├── pause.png ├── play.png ├── prev.png ├── pywd.ico ├── single_conjunction.ui ├── starpositions_widget.ui └── syntheticcurve_widget.ui └── src ├── __init__.py ├── constants.py ├── helpers ├── __init__.py ├── matplotlib_embedder.py ├── messenger.py ├── methods.py └── wd_utils │ ├── __init__.py │ ├── wd_constants.py │ ├── wd_containers.py │ └── wd_io.py └── interfaces ├── __init__.py ├── configurespots_interface.py ├── conjunction_interface.py ├── curveproperties_interface.py ├── dc_interface.py ├── dimension_interface.py ├── eclipsetimings_interface.py ├── history_interface.py ├── lcdcpicker_interface.py ├── lineprofile_interface.py ├── loadobservations_interface.py ├── mainwindow_interface.py ├── oc_interface.py ├── single_conjunction.py ├── starpositions_interface.py └── syntheticcurve_interface.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Ozan Güzel, Orkun Özdarcan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyWD2015-Qt5 2 | A Qt5 GUI written in Python for Wilson - Devinney eclipsing binary modeling software. 3 | 4 | IMPORTANT NOTE: TESS bandpass was added to PyWD2015. However, users must get updated atmosphere and limb darkening files from https://faculty.fiu.edu/~vanhamme/wdfiles/lcdc-datafiles-2019.tar.gz in order to run PyWD2015 properly. 5 | 6 | PyWD2015 v1.0.0 is released (16th August 2022). Please visit [releases](https://github.com/Varnani/pywd2015-qt5/releases) page and [download](https://github.com/Varnani/pywd2015-qt5/releases/download/v1.0.0/wd-precompiled.zip) all required files, including executable binaries, auxiliary files and source codes. 7 | 8 | A comprehensive user manual is also available in [this link](https://github.com/Varnani/pywd2015-qt5/releases/download/v1.0.0/PyWD2015_qt5_manual.pdf). 9 | 10 | Single executable file is [available](https://github.com/Varnani/pywd2015-qt5/releases/download/v1.0.0/pywd2015_win64bit_16August2022.exe) for Windows 7, 8.x and 10 (all 64 bit) operating systems. 11 | 12 | ## First Things First 13 | If you happen to use this software in a scientific work, please cite PyWD2015 release proceeding: 14 | [CoSka (2020), 50, 535](https://ui.adsabs.harvard.edu/abs/2020CoSka..50..535G/abstract) 15 | 16 | You must also properly cite relevant Wilson - Devinney papers: 17 | [ApJ (1971), 166, 605](https://ui.adsabs.harvard.edu/abs/1971ApJ...166..605W/abstract) 18 | [ApJ (1979), 234, 1054](https://ui.adsabs.harvard.edu/abs/1979ApJ...234.1054W/abstract) 19 | [ApJ (1990), 356, 613](https://ui.adsabs.harvard.edu/abs/1990ApJ...356..613W/abstract) 20 | [ApJ (2007), 661, 1129](https://ui.adsabs.harvard.edu/abs/2007ApJ...661.1129V/abstract) 21 | [ApJ (2008), 672, 575](https://ui.adsabs.harvard.edu/abs/2008ApJ...672..575W/abstract) 22 | [AJ (2012), 144, 73](https://ui.adsabs.harvard.edu/abs/2012AJ....144...73W/abstract) 23 | [ApJ (2014), 780, 151](https://ui.adsabs.harvard.edu/abs/2014ApJ...780..151W/abstract) 24 | 25 | ## Installing Dependencies 26 | 27 | > **WARNING** | Some Linux distributions use Python 3.x as their default Python interpreter. In that case 'python' command and package name prefix will actually refer to Python 3.x and 'python2' will refer to Python 2.7. Please refer to your distributions package manager database if you are unsure. On Windows, multiple Python installations may conflict with each other, and your 'python' command might run a different version rather than what you intented. Run 'python --version' from command line to check your Python version. 28 | 29 | PyWD2015 supports Python 2.7 and 3.5+. It also relies on Numpy, Scipy, Matplotlib libraries. These libraries can be installed using pip, the Python package installer. Pip should be automatically installed alongside Python on Windows. On Linux, you may need to install pip with your package manager. On Ubuntu and Debian, you can issue: 30 | 31 | ```shell 32 | (For Python 2.7) sudo apt install python-pip 33 | (For Python 3.x) sudo apt install python3-pip 34 | ``` 35 | 36 | to install pip. You can then install the dependencies with the following command: 37 | 38 | ```shell 39 | Linux: 40 | (For Python 2.7) sudo python -m pip install numpy scipy matplotlib 41 | (For Python 3.x) sudo python3 -m pip install numpy scipy matplotlib 42 | 43 | Windows: 44 | python -m pip install numpy scipy matplotlib 45 | ``` 46 | 47 | On Debian, you may encounter a "backports.functools_lru_cache" and/or "tkinter" error on a fresh matplotlib installation under Python 2.7. To fix this, you can issue: 48 | 49 | ```shell 50 | sudo apt install python-backports.functools-lru-cache python-tk 51 | ``` 52 | 53 | After that, you need to install the PyQt5 library. 54 | 55 | ### Linux 56 | Installing PyQt5 on Linux depends on your distribution and package manager. In general, you should not use pip to install PyQt5, instead use your distributions package manager. On Ubuntu and Debian you can use: 57 | 58 | ```shell 59 | (For Python 2.7) sudo apt install python-pyqt5 60 | (For Python 3.x) sudo apt install python3-pyqt5 61 | ``` 62 | 63 | ### Windows 64 | You can safely use pip to install PyQt5 on Windows 7 and Windows 8.x operating systems: 65 | 66 | ```shell 67 | python -m pip install python-qt5 68 | ``` 69 | 70 | However, for the latest versions of Python (3.7+) Windows 10 users may have to modify 71 | the command as shown below: 72 | 73 | ```shell 74 | python -m pip install PyQT5 75 | ``` 76 | 77 | In some Windows operating systems with older Python versions (especially 3.5 or 3.6), users may experience "dll import error" when trying to run PyWD2015. This issue is usually related to PyQT5 and may not have a unique reason. In many case, finding a solution might be time-consuming. In order to avoid this issue, uninstalling the older version and then installing the latest available Python version is strongly recommended. After that, users should install required libraries as described above, as well as PyQT5. 78 | 79 | PyWD2015 has not been tested on Windows 11 yet. 80 | 81 | ## Getting Started 82 | 83 | After installing required dependencies, you can get the source code of the program by either cloning this repository, or downloading a release from the [Releases](https://github.com/Varnani/pywd2015-qt5/releases) page. Extract the source code and issue this command to start the PyWD2015: 84 | 85 | ```shell 86 | python pywd2015.py 87 | ``` 88 | 89 | To run calculations, you need to provide the paths of compiled DC and LC programs of the Wilson - Devinney code. Precompiled versions are hosted here with the permission of Dr. Robert E. Wilson. These too can be found on the "Releases" page. You can also compile the WD binaries yourself. Source files can be found at ftp://ftp.astro.ufl.edu/pub/wilson/lcdc2015/ (the WD Homepage). 90 | 91 | GUI is mostly self-explanatory, and most labels contain tooltips, but "Releases" page also contains a user manual. While this manual is based on a deprecated, Qt4 version of PyWD2015, nearly all the concepts discussed there also applies to the Qt5 version. 92 | 93 | ## Contact 94 | 95 | If you have any questions, you can reach the authors from: 96 | 97 | ``` 98 | Ozan Güzel: ozanguzel35@outlook.com 99 | Dr. Orkun Özdarcan: orkun.ozdarcan@ege.edu.tr 100 | ``` 101 | -------------------------------------------------------------------------------- /gui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/gui/__init__.py -------------------------------------------------------------------------------- /gui/dimensions_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'dimensions_widget.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_DimensionWidget(object): 12 | def setupUi(self, DimensionWidget): 13 | DimensionWidget.setObjectName("DimensionWidget") 14 | DimensionWidget.resize(1000, 600) 15 | self.gridLayout_5 = QtWidgets.QGridLayout(DimensionWidget) 16 | self.gridLayout_5.setObjectName("gridLayout_5") 17 | self.groupBox_2 = QtWidgets.QGroupBox(DimensionWidget) 18 | self.groupBox_2.setObjectName("groupBox_2") 19 | self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox_2) 20 | self.verticalLayout.setObjectName("verticalLayout") 21 | self.s1_plot_widget = QtWidgets.QWidget(self.groupBox_2) 22 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) 23 | sizePolicy.setHorizontalStretch(0) 24 | sizePolicy.setVerticalStretch(0) 25 | sizePolicy.setHeightForWidth(self.s1_plot_widget.sizePolicy().hasHeightForWidth()) 26 | self.s1_plot_widget.setSizePolicy(sizePolicy) 27 | self.s1_plot_widget.setMinimumSize(QtCore.QSize(300, 200)) 28 | self.s1_plot_widget.setObjectName("s1_plot_widget") 29 | self.verticalLayout.addWidget(self.s1_plot_widget) 30 | self.line_2 = QtWidgets.QFrame(self.groupBox_2) 31 | self.line_2.setFrameShape(QtWidgets.QFrame.HLine) 32 | self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) 33 | self.line_2.setObjectName("line_2") 34 | self.verticalLayout.addWidget(self.line_2) 35 | self.horizontalLayout = QtWidgets.QHBoxLayout() 36 | self.horizontalLayout.setObjectName("horizontalLayout") 37 | self.s1_pole_chk = QtWidgets.QCheckBox(self.groupBox_2) 38 | palette = QtGui.QPalette() 39 | brush = QtGui.QBrush(QtGui.QColor(0, 48, 255)) 40 | brush.setStyle(QtCore.Qt.SolidPattern) 41 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) 42 | brush = QtGui.QBrush(QtGui.QColor(0, 48, 255)) 43 | brush.setStyle(QtCore.Qt.SolidPattern) 44 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) 45 | brush = QtGui.QBrush(QtGui.QColor(190, 190, 190)) 46 | brush.setStyle(QtCore.Qt.SolidPattern) 47 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) 48 | self.s1_pole_chk.setPalette(palette) 49 | font = QtGui.QFont() 50 | font.setBold(True) 51 | font.setWeight(75) 52 | self.s1_pole_chk.setFont(font) 53 | self.s1_pole_chk.setChecked(True) 54 | self.s1_pole_chk.setObjectName("s1_pole_chk") 55 | self.horizontalLayout.addWidget(self.s1_pole_chk) 56 | self.s1_point_chk = QtWidgets.QCheckBox(self.groupBox_2) 57 | font = QtGui.QFont() 58 | font.setBold(True) 59 | font.setWeight(75) 60 | self.s1_point_chk.setFont(font) 61 | self.s1_point_chk.setObjectName("s1_point_chk") 62 | self.horizontalLayout.addWidget(self.s1_point_chk) 63 | self.s1_side_chk = QtWidgets.QCheckBox(self.groupBox_2) 64 | palette = QtGui.QPalette() 65 | brush = QtGui.QBrush(QtGui.QColor(239, 41, 41)) 66 | brush.setStyle(QtCore.Qt.SolidPattern) 67 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) 68 | brush = QtGui.QBrush(QtGui.QColor(239, 41, 41)) 69 | brush.setStyle(QtCore.Qt.SolidPattern) 70 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) 71 | brush = QtGui.QBrush(QtGui.QColor(190, 190, 190)) 72 | brush.setStyle(QtCore.Qt.SolidPattern) 73 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) 74 | self.s1_side_chk.setPalette(palette) 75 | font = QtGui.QFont() 76 | font.setBold(True) 77 | font.setWeight(75) 78 | self.s1_side_chk.setFont(font) 79 | self.s1_side_chk.setObjectName("s1_side_chk") 80 | self.horizontalLayout.addWidget(self.s1_side_chk) 81 | self.s1_back_chk = QtWidgets.QCheckBox(self.groupBox_2) 82 | palette = QtGui.QPalette() 83 | brush = QtGui.QBrush(QtGui.QColor(115, 210, 22)) 84 | brush.setStyle(QtCore.Qt.SolidPattern) 85 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) 86 | brush = QtGui.QBrush(QtGui.QColor(115, 210, 22)) 87 | brush.setStyle(QtCore.Qt.SolidPattern) 88 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) 89 | brush = QtGui.QBrush(QtGui.QColor(190, 190, 190)) 90 | brush.setStyle(QtCore.Qt.SolidPattern) 91 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) 92 | self.s1_back_chk.setPalette(palette) 93 | font = QtGui.QFont() 94 | font.setBold(True) 95 | font.setWeight(75) 96 | self.s1_back_chk.setFont(font) 97 | self.s1_back_chk.setObjectName("s1_back_chk") 98 | self.horizontalLayout.addWidget(self.s1_back_chk) 99 | self.verticalLayout.addLayout(self.horizontalLayout) 100 | self.gridLayout_5.addWidget(self.groupBox_2, 0, 0, 1, 1) 101 | self.groupBox = QtWidgets.QGroupBox(DimensionWidget) 102 | self.groupBox.setObjectName("groupBox") 103 | self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox) 104 | self.gridLayout_3.setObjectName("gridLayout_3") 105 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout() 106 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 107 | self.s2_pole_chk = QtWidgets.QCheckBox(self.groupBox) 108 | palette = QtGui.QPalette() 109 | brush = QtGui.QBrush(QtGui.QColor(0, 48, 255)) 110 | brush.setStyle(QtCore.Qt.SolidPattern) 111 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) 112 | brush = QtGui.QBrush(QtGui.QColor(0, 48, 255)) 113 | brush.setStyle(QtCore.Qt.SolidPattern) 114 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) 115 | brush = QtGui.QBrush(QtGui.QColor(190, 190, 190)) 116 | brush.setStyle(QtCore.Qt.SolidPattern) 117 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) 118 | self.s2_pole_chk.setPalette(palette) 119 | font = QtGui.QFont() 120 | font.setBold(True) 121 | font.setWeight(75) 122 | self.s2_pole_chk.setFont(font) 123 | self.s2_pole_chk.setChecked(True) 124 | self.s2_pole_chk.setObjectName("s2_pole_chk") 125 | self.horizontalLayout_2.addWidget(self.s2_pole_chk) 126 | self.s2_point_chk = QtWidgets.QCheckBox(self.groupBox) 127 | font = QtGui.QFont() 128 | font.setBold(True) 129 | font.setWeight(75) 130 | self.s2_point_chk.setFont(font) 131 | self.s2_point_chk.setObjectName("s2_point_chk") 132 | self.horizontalLayout_2.addWidget(self.s2_point_chk) 133 | self.s2_side_chk = QtWidgets.QCheckBox(self.groupBox) 134 | palette = QtGui.QPalette() 135 | brush = QtGui.QBrush(QtGui.QColor(239, 41, 41)) 136 | brush.setStyle(QtCore.Qt.SolidPattern) 137 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) 138 | brush = QtGui.QBrush(QtGui.QColor(239, 41, 41)) 139 | brush.setStyle(QtCore.Qt.SolidPattern) 140 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) 141 | brush = QtGui.QBrush(QtGui.QColor(190, 190, 190)) 142 | brush.setStyle(QtCore.Qt.SolidPattern) 143 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) 144 | self.s2_side_chk.setPalette(palette) 145 | font = QtGui.QFont() 146 | font.setBold(True) 147 | font.setWeight(75) 148 | self.s2_side_chk.setFont(font) 149 | self.s2_side_chk.setObjectName("s2_side_chk") 150 | self.horizontalLayout_2.addWidget(self.s2_side_chk) 151 | self.s2_back_chk = QtWidgets.QCheckBox(self.groupBox) 152 | palette = QtGui.QPalette() 153 | brush = QtGui.QBrush(QtGui.QColor(115, 210, 22)) 154 | brush.setStyle(QtCore.Qt.SolidPattern) 155 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) 156 | brush = QtGui.QBrush(QtGui.QColor(115, 210, 22)) 157 | brush.setStyle(QtCore.Qt.SolidPattern) 158 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) 159 | brush = QtGui.QBrush(QtGui.QColor(190, 190, 190)) 160 | brush.setStyle(QtCore.Qt.SolidPattern) 161 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) 162 | self.s2_back_chk.setPalette(palette) 163 | font = QtGui.QFont() 164 | font.setBold(True) 165 | font.setWeight(75) 166 | self.s2_back_chk.setFont(font) 167 | self.s2_back_chk.setObjectName("s2_back_chk") 168 | self.horizontalLayout_2.addWidget(self.s2_back_chk) 169 | self.gridLayout_3.addLayout(self.horizontalLayout_2, 2, 0, 1, 1) 170 | self.s2_plot_widget = QtWidgets.QWidget(self.groupBox) 171 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) 172 | sizePolicy.setHorizontalStretch(0) 173 | sizePolicy.setVerticalStretch(0) 174 | sizePolicy.setHeightForWidth(self.s2_plot_widget.sizePolicy().hasHeightForWidth()) 175 | self.s2_plot_widget.setSizePolicy(sizePolicy) 176 | self.s2_plot_widget.setMinimumSize(QtCore.QSize(300, 200)) 177 | self.s2_plot_widget.setObjectName("s2_plot_widget") 178 | self.gridLayout_3.addWidget(self.s2_plot_widget, 0, 0, 1, 1) 179 | self.line_3 = QtWidgets.QFrame(self.groupBox) 180 | self.line_3.setFrameShape(QtWidgets.QFrame.HLine) 181 | self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken) 182 | self.line_3.setObjectName("line_3") 183 | self.gridLayout_3.addWidget(self.line_3, 1, 0, 1, 1) 184 | self.gridLayout_5.addWidget(self.groupBox, 0, 1, 1, 1) 185 | self.line = QtWidgets.QFrame(DimensionWidget) 186 | self.line.setFrameShape(QtWidgets.QFrame.HLine) 187 | self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 188 | self.line.setObjectName("line") 189 | self.gridLayout_5.addWidget(self.line, 3, 0, 1, 2) 190 | self.plot_btn = QtWidgets.QPushButton(DimensionWidget) 191 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) 192 | sizePolicy.setHorizontalStretch(0) 193 | sizePolicy.setVerticalStretch(0) 194 | sizePolicy.setHeightForWidth(self.plot_btn.sizePolicy().hasHeightForWidth()) 195 | self.plot_btn.setSizePolicy(sizePolicy) 196 | self.plot_btn.setObjectName("plot_btn") 197 | self.gridLayout_5.addWidget(self.plot_btn, 4, 0, 1, 2) 198 | 199 | self.retranslateUi(DimensionWidget) 200 | QtCore.QMetaObject.connectSlotsByName(DimensionWidget) 201 | 202 | def retranslateUi(self, DimensionWidget): 203 | _translate = QtCore.QCoreApplication.translate 204 | DimensionWidget.setWindowTitle(_translate("DimensionWidget", "Component Dimensions")) 205 | self.groupBox_2.setTitle(_translate("DimensionWidget", "Star 1")) 206 | self.s1_pole_chk.setText(_translate("DimensionWidget", "Pole")) 207 | self.s1_point_chk.setText(_translate("DimensionWidget", "Point")) 208 | self.s1_side_chk.setText(_translate("DimensionWidget", "Side")) 209 | self.s1_back_chk.setText(_translate("DimensionWidget", "Back")) 210 | self.groupBox.setTitle(_translate("DimensionWidget", "Star 2")) 211 | self.s2_pole_chk.setText(_translate("DimensionWidget", "Pole")) 212 | self.s2_point_chk.setText(_translate("DimensionWidget", "Point")) 213 | self.s2_side_chk.setText(_translate("DimensionWidget", "Side")) 214 | self.s2_back_chk.setText(_translate("DimensionWidget", "Back")) 215 | self.plot_btn.setText(_translate("DimensionWidget", "Calculate Component Radii")) 216 | 217 | -------------------------------------------------------------------------------- /gui/eclipsetimings_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'eclipsetimings_widget.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_EclipseWidget(object): 12 | def setupUi(self, EclipseWidget): 13 | EclipseWidget.setObjectName("EclipseWidget") 14 | EclipseWidget.resize(375, 600) 15 | EclipseWidget.setMinimumSize(QtCore.QSize(375, 600)) 16 | EclipseWidget.setMaximumSize(QtCore.QSize(400, 900)) 17 | self.gridLayout = QtWidgets.QGridLayout(EclipseWidget) 18 | self.gridLayout.setObjectName("gridLayout") 19 | self.label_16 = QtWidgets.QLabel(EclipseWidget) 20 | self.label_16.setObjectName("label_16") 21 | self.gridLayout.addWidget(self.label_16, 5, 0, 1, 1) 22 | self.ksd_box = QtWidgets.QSpinBox(EclipseWidget) 23 | self.ksd_box.setButtonSymbols(QtWidgets.QAbstractSpinBox.UpDownArrows) 24 | self.ksd_box.setMinimum(0) 25 | self.ksd_box.setMaximum(2) 26 | self.ksd_box.setProperty("value", 1) 27 | self.ksd_box.setObjectName("ksd_box") 28 | self.gridLayout.addWidget(self.ksd_box, 5, 1, 1, 1) 29 | self.datawidget = QtWidgets.QTreeWidget(EclipseWidget) 30 | self.datawidget.setObjectName("datawidget") 31 | self.gridLayout.addWidget(self.datawidget, 9, 0, 1, 5) 32 | self.label_11 = QtWidgets.QLabel(EclipseWidget) 33 | self.label_11.setObjectName("label_11") 34 | self.gridLayout.addWidget(self.label_11, 5, 3, 1, 1) 35 | self.label = QtWidgets.QLabel(EclipseWidget) 36 | self.label.setObjectName("label") 37 | self.gridLayout.addWidget(self.label, 7, 0, 1, 2) 38 | self.constant_weight_checkbox = QtWidgets.QCheckBox(EclipseWidget) 39 | self.constant_weight_checkbox.setObjectName("constant_weight_checkbox") 40 | self.gridLayout.addWidget(self.constant_weight_checkbox, 3, 0, 1, 5) 41 | self.filepath_label = QtWidgets.QLabel(EclipseWidget) 42 | self.filepath_label.setObjectName("filepath_label") 43 | self.gridLayout.addWidget(self.filepath_label, 8, 0, 1, 5) 44 | self.line_12 = QtWidgets.QFrame(EclipseWidget) 45 | self.line_12.setFrameShape(QtWidgets.QFrame.HLine) 46 | self.line_12.setFrameShadow(QtWidgets.QFrame.Sunken) 47 | self.line_12.setObjectName("line_12") 48 | self.gridLayout.addWidget(self.line_12, 1, 0, 1, 5) 49 | self.line_2 = QtWidgets.QFrame(EclipseWidget) 50 | self.line_2.setFrameShape(QtWidgets.QFrame.HLine) 51 | self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) 52 | self.line_2.setObjectName("line_2") 53 | self.gridLayout.addWidget(self.line_2, 4, 0, 1, 5) 54 | self.line_13 = QtWidgets.QFrame(EclipseWidget) 55 | self.line_13.setFrameShape(QtWidgets.QFrame.HLine) 56 | self.line_13.setFrameShadow(QtWidgets.QFrame.Sunken) 57 | self.line_13.setObjectName("line_13") 58 | self.gridLayout.addWidget(self.line_13, 6, 0, 1, 5) 59 | self.label_53 = QtWidgets.QLabel(EclipseWidget) 60 | self.label_53.setObjectName("label_53") 61 | self.gridLayout.addWidget(self.label_53, 0, 0, 1, 5) 62 | self.line = QtWidgets.QFrame(EclipseWidget) 63 | self.line.setFrameShape(QtWidgets.QFrame.VLine) 64 | self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 65 | self.line.setObjectName("line") 66 | self.gridLayout.addWidget(self.line, 5, 2, 1, 1) 67 | self.iftime_chk = QtWidgets.QCheckBox(EclipseWidget) 68 | self.iftime_chk.setObjectName("iftime_chk") 69 | self.gridLayout.addWidget(self.iftime_chk, 2, 0, 1, 4) 70 | self.load_btn = QtWidgets.QPushButton(EclipseWidget) 71 | self.load_btn.setObjectName("load_btn") 72 | self.gridLayout.addWidget(self.load_btn, 10, 0, 1, 5) 73 | self.clear_btn = QtWidgets.QPushButton(EclipseWidget) 74 | self.clear_btn.setObjectName("clear_btn") 75 | self.gridLayout.addWidget(self.clear_btn, 11, 0, 1, 5) 76 | self.sigma_ipt = QtWidgets.QDoubleSpinBox(EclipseWidget) 77 | self.sigma_ipt.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) 78 | self.sigma_ipt.setDecimals(8) 79 | self.sigma_ipt.setMaximum(99999.0) 80 | self.sigma_ipt.setObjectName("sigma_ipt") 81 | self.gridLayout.addWidget(self.sigma_ipt, 5, 4, 1, 1) 82 | 83 | self.retranslateUi(EclipseWidget) 84 | QtCore.QMetaObject.connectSlotsByName(EclipseWidget) 85 | 86 | def retranslateUi(self, EclipseWidget): 87 | _translate = QtCore.QCoreApplication.translate 88 | EclipseWidget.setWindowTitle(_translate("EclipseWidget", "Eclipse Timings")) 89 | self.label_16.setToolTip(_translate("EclipseWidget", "Set standard deviation apply method. [?]")) 90 | self.label_16.setWhatsThis(_translate("EclipseWidget", "

An integer array that is 0, 1, or 2 for each input sub-dataset (velocity, light, or eclipse timings).

The KSDs tell DC whether to apply the input standard deviations (σ’s) to compute curvedependent weights (KSD=0),

to apply DC’s internally computed σ’s for the weights (KSD=1),

or to apply σ’s based on one or two restricted phase ranges for the weights (KSD=2).

If unsure, set to 1.

")) 91 | self.label_16.setText(_translate("EclipseWidget", "KSD")) 92 | self.datawidget.headerItem().setText(0, _translate("EclipseWidget", "Time")) 93 | self.datawidget.headerItem().setText(1, _translate("EclipseWidget", "Eclipse Type")) 94 | self.datawidget.headerItem().setText(2, _translate("EclipseWidget", "Weight")) 95 | self.label_11.setToolTip(_translate("EclipseWidget", "Estimated standard deviation of observed light")) 96 | self.label_11.setText(_translate("EclipseWidget", "SIGMA")) 97 | self.label.setText(_translate("EclipseWidget", "Data preview of file:")) 98 | self.constant_weight_checkbox.setToolTip(_translate("EclipseWidget", "

If checked, third column will be ignored and all weights will be assumed as unity.

If there isn\'t a third column, program will fill weights with unity too, regardless of this option.

")) 99 | self.constant_weight_checkbox.setText(_translate("EclipseWidget", "Use constant weights (1.0)")) 100 | self.filepath_label.setText(_translate("EclipseWidget", "None")) 101 | self.label_53.setText(_translate("EclipseWidget", "Load eclipse timings from a file")) 102 | self.iftime_chk.setText(_translate("EclipseWidget", "IFTIME - Write eclipse timings")) 103 | self.load_btn.setText(_translate("EclipseWidget", "Load")) 104 | self.clear_btn.setText(_translate("EclipseWidget", "Clear")) 105 | 106 | 107 | if __name__ == "__main__": 108 | import sys 109 | app = QtWidgets.QApplication(sys.argv) 110 | EclipseWidget = QtWidgets.QWidget() 111 | ui = Ui_EclipseWidget() 112 | ui.setupUi(EclipseWidget) 113 | EclipseWidget.show() 114 | sys.exit(app.exec_()) 115 | 116 | -------------------------------------------------------------------------------- /gui/history_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'history_widget.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_HistoryWidget(object): 12 | def setupUi(self, HistoryWidget): 13 | HistoryWidget.setObjectName("HistoryWidget") 14 | HistoryWidget.resize(900, 500) 15 | self.gridLayout_3 = QtWidgets.QGridLayout(HistoryWidget) 16 | self.gridLayout_3.setObjectName("gridLayout_3") 17 | self.gridLayout = QtWidgets.QGridLayout() 18 | self.gridLayout.setObjectName("gridLayout") 19 | self.gridLayout_2 = QtWidgets.QGridLayout() 20 | self.gridLayout_2.setObjectName("gridLayout_2") 21 | self.plot_btn = QtWidgets.QPushButton(HistoryWidget) 22 | self.plot_btn.setObjectName("plot_btn") 23 | self.gridLayout_2.addWidget(self.plot_btn, 0, 0, 1, 1) 24 | self.auto_chk = QtWidgets.QCheckBox(HistoryWidget) 25 | self.auto_chk.setObjectName("auto_chk") 26 | self.gridLayout_2.addWidget(self.auto_chk, 0, 1, 1, 1) 27 | self.clear_btn = QtWidgets.QPushButton(HistoryWidget) 28 | self.clear_btn.setObjectName("clear_btn") 29 | self.gridLayout_2.addWidget(self.clear_btn, 1, 0, 1, 1) 30 | self.export_btn = QtWidgets.QPushButton(HistoryWidget) 31 | self.export_btn.setObjectName("export_btn") 32 | self.gridLayout_2.addWidget(self.export_btn, 1, 1, 1, 1) 33 | self.gridLayout.addLayout(self.gridLayout_2, 2, 0, 1, 1) 34 | self.history_treewidget = QtWidgets.QTreeWidget(HistoryWidget) 35 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding) 36 | sizePolicy.setHorizontalStretch(0) 37 | sizePolicy.setVerticalStretch(0) 38 | sizePolicy.setHeightForWidth(self.history_treewidget.sizePolicy().hasHeightForWidth()) 39 | self.history_treewidget.setSizePolicy(sizePolicy) 40 | self.history_treewidget.setMinimumSize(QtCore.QSize(400, 0)) 41 | self.history_treewidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectColumns) 42 | self.history_treewidget.setObjectName("history_treewidget") 43 | self.gridLayout.addWidget(self.history_treewidget, 0, 0, 1, 1) 44 | self.line_2 = QtWidgets.QFrame(HistoryWidget) 45 | self.line_2.setFrameShape(QtWidgets.QFrame.HLine) 46 | self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) 47 | self.line_2.setObjectName("line_2") 48 | self.gridLayout.addWidget(self.line_2, 1, 0, 1, 1) 49 | self.plot_widget = QtWidgets.QWidget(HistoryWidget) 50 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) 51 | sizePolicy.setHorizontalStretch(0) 52 | sizePolicy.setVerticalStretch(0) 53 | sizePolicy.setHeightForWidth(self.plot_widget.sizePolicy().hasHeightForWidth()) 54 | self.plot_widget.setSizePolicy(sizePolicy) 55 | self.plot_widget.setMinimumSize(QtCore.QSize(300, 300)) 56 | self.plot_widget.setObjectName("plot_widget") 57 | self.gridLayout.addWidget(self.plot_widget, 0, 2, 3, 1) 58 | self.line = QtWidgets.QFrame(HistoryWidget) 59 | self.line.setFrameShape(QtWidgets.QFrame.VLine) 60 | self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 61 | self.line.setObjectName("line") 62 | self.gridLayout.addWidget(self.line, 0, 1, 3, 1) 63 | self.gridLayout_3.addLayout(self.gridLayout, 0, 0, 1, 1) 64 | 65 | self.retranslateUi(HistoryWidget) 66 | QtCore.QMetaObject.connectSlotsByName(HistoryWidget) 67 | 68 | def retranslateUi(self, HistoryWidget): 69 | _translate = QtCore.QCoreApplication.translate 70 | HistoryWidget.setWindowTitle(_translate("HistoryWidget", "Solution History")) 71 | self.plot_btn.setText(_translate("HistoryWidget", "Plot")) 72 | self.auto_chk.setToolTip(_translate("HistoryWidget", "Automatically plot selected parameter when DC program finishes its calculation")) 73 | self.auto_chk.setText(_translate("HistoryWidget", "Auto")) 74 | self.clear_btn.setText(_translate("HistoryWidget", "Clear")) 75 | self.export_btn.setText(_translate("HistoryWidget", "Export All")) 76 | 77 | -------------------------------------------------------------------------------- /gui/lcdcpicker_dialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'lcdcpicker_dialog.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_LCDCPickerDialog(object): 12 | def setupUi(self, LCDCPickerDialog): 13 | LCDCPickerDialog.setObjectName("LCDCPickerDialog") 14 | LCDCPickerDialog.resize(700, 500) 15 | LCDCPickerDialog.setMinimumSize(QtCore.QSize(700, 500)) 16 | LCDCPickerDialog.setMaximumSize(QtCore.QSize(700, 500)) 17 | self.gridLayout_4 = QtWidgets.QGridLayout(LCDCPickerDialog) 18 | self.gridLayout_4.setObjectName("gridLayout_4") 19 | self.groupBox = QtWidgets.QGroupBox(LCDCPickerDialog) 20 | self.groupBox.setObjectName("groupBox") 21 | self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) 22 | self.gridLayout_2.setObjectName("gridLayout_2") 23 | self.pickdc_btn = QtWidgets.QPushButton(self.groupBox) 24 | self.pickdc_btn.setObjectName("pickdc_btn") 25 | self.gridLayout_2.addWidget(self.pickdc_btn, 1, 3, 1, 1) 26 | self.label_68 = QtWidgets.QLabel(self.groupBox) 27 | self.label_68.setObjectName("label_68") 28 | self.gridLayout_2.addWidget(self.label_68, 0, 0, 1, 1) 29 | self.label_67 = QtWidgets.QLabel(self.groupBox) 30 | self.label_67.setObjectName("label_67") 31 | self.gridLayout_2.addWidget(self.label_67, 1, 0, 1, 1) 32 | self.picklc_btn = QtWidgets.QPushButton(self.groupBox) 33 | self.picklc_btn.setObjectName("picklc_btn") 34 | self.gridLayout_2.addWidget(self.picklc_btn, 0, 3, 1, 1) 35 | self.dcpath_label = QtWidgets.QLabel(self.groupBox) 36 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) 37 | sizePolicy.setHorizontalStretch(0) 38 | sizePolicy.setVerticalStretch(0) 39 | sizePolicy.setHeightForWidth(self.dcpath_label.sizePolicy().hasHeightForWidth()) 40 | self.dcpath_label.setSizePolicy(sizePolicy) 41 | self.dcpath_label.setText("") 42 | self.dcpath_label.setObjectName("dcpath_label") 43 | self.gridLayout_2.addWidget(self.dcpath_label, 1, 2, 1, 1) 44 | self.lcpath_label = QtWidgets.QLabel(self.groupBox) 45 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) 46 | sizePolicy.setHorizontalStretch(0) 47 | sizePolicy.setVerticalStretch(0) 48 | sizePolicy.setHeightForWidth(self.lcpath_label.sizePolicy().hasHeightForWidth()) 49 | self.lcpath_label.setSizePolicy(sizePolicy) 50 | self.lcpath_label.setText("") 51 | self.lcpath_label.setObjectName("lcpath_label") 52 | self.gridLayout_2.addWidget(self.lcpath_label, 0, 1, 1, 2) 53 | self.gridLayout_4.addWidget(self.groupBox, 3, 0, 1, 2) 54 | self.groupBox_2 = QtWidgets.QGroupBox(LCDCPickerDialog) 55 | self.groupBox_2.setObjectName("groupBox_2") 56 | self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_2) 57 | self.gridLayout_3.setObjectName("gridLayout_3") 58 | self.gridLayout = QtWidgets.QGridLayout() 59 | self.gridLayout.setObjectName("gridLayout") 60 | self.label_65 = QtWidgets.QLabel(self.groupBox_2) 61 | self.label_65.setObjectName("label_65") 62 | self.gridLayout.addWidget(self.label_65, 1, 0, 1, 1) 63 | self.lineEdit = QtWidgets.QLineEdit(self.groupBox_2) 64 | self.lineEdit.setReadOnly(True) 65 | self.lineEdit.setObjectName("lineEdit") 66 | self.gridLayout.addWidget(self.lineEdit, 0, 2, 1, 1) 67 | self.label_66 = QtWidgets.QLabel(self.groupBox_2) 68 | self.label_66.setObjectName("label_66") 69 | self.gridLayout.addWidget(self.label_66, 0, 0, 1, 1) 70 | self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_2) 71 | self.lineEdit_2.setReadOnly(True) 72 | self.lineEdit_2.setObjectName("lineEdit_2") 73 | self.gridLayout.addWidget(self.lineEdit_2, 1, 2, 1, 1) 74 | spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) 75 | self.gridLayout.addItem(spacerItem, 0, 1, 1, 1) 76 | spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) 77 | self.gridLayout.addItem(spacerItem1, 1, 1, 1, 1) 78 | self.gridLayout_3.addLayout(self.gridLayout, 0, 0, 1, 1) 79 | self.gridLayout_4.addWidget(self.groupBox_2, 4, 0, 1, 2) 80 | self.line = QtWidgets.QFrame(LCDCPickerDialog) 81 | self.line.setFrameShape(QtWidgets.QFrame.HLine) 82 | self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 83 | self.line.setObjectName("line") 84 | self.gridLayout_4.addWidget(self.line, 1, 0, 1, 2) 85 | self.label_2 = QtWidgets.QLabel(LCDCPickerDialog) 86 | self.label_2.setTextFormat(QtCore.Qt.PlainText) 87 | self.label_2.setScaledContents(False) 88 | self.label_2.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignTop) 89 | self.label_2.setWordWrap(True) 90 | self.label_2.setObjectName("label_2") 91 | self.gridLayout_4.addWidget(self.label_2, 2, 0, 1, 2) 92 | self.label = QtWidgets.QLabel(LCDCPickerDialog) 93 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 94 | sizePolicy.setHorizontalStretch(0) 95 | sizePolicy.setVerticalStretch(0) 96 | sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) 97 | self.label.setSizePolicy(sizePolicy) 98 | font = QtGui.QFont() 99 | font.setPointSize(15) 100 | font.setBold(True) 101 | font.setWeight(75) 102 | self.label.setFont(font) 103 | self.label.setObjectName("label") 104 | self.gridLayout_4.addWidget(self.label, 0, 0, 1, 1) 105 | self.horizontalLayout = QtWidgets.QHBoxLayout() 106 | self.horizontalLayout.setObjectName("horizontalLayout") 107 | self.save_btn = QtWidgets.QPushButton(LCDCPickerDialog) 108 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) 109 | sizePolicy.setHorizontalStretch(0) 110 | sizePolicy.setVerticalStretch(0) 111 | sizePolicy.setHeightForWidth(self.save_btn.sizePolicy().hasHeightForWidth()) 112 | self.save_btn.setSizePolicy(sizePolicy) 113 | self.save_btn.setObjectName("save_btn") 114 | self.horizontalLayout.addWidget(self.save_btn) 115 | self.exit_btn = QtWidgets.QPushButton(LCDCPickerDialog) 116 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) 117 | sizePolicy.setHorizontalStretch(0) 118 | sizePolicy.setVerticalStretch(0) 119 | sizePolicy.setHeightForWidth(self.exit_btn.sizePolicy().hasHeightForWidth()) 120 | self.exit_btn.setSizePolicy(sizePolicy) 121 | self.exit_btn.setObjectName("exit_btn") 122 | self.horizontalLayout.addWidget(self.exit_btn) 123 | self.gridLayout_4.addLayout(self.horizontalLayout, 6, 0, 1, 2) 124 | self.line_2 = QtWidgets.QFrame(LCDCPickerDialog) 125 | self.line_2.setFrameShape(QtWidgets.QFrame.HLine) 126 | self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) 127 | self.line_2.setObjectName("line_2") 128 | self.gridLayout_4.addWidget(self.line_2, 5, 0, 1, 2) 129 | 130 | self.retranslateUi(LCDCPickerDialog) 131 | QtCore.QMetaObject.connectSlotsByName(LCDCPickerDialog) 132 | 133 | def retranslateUi(self, LCDCPickerDialog): 134 | _translate = QtCore.QCoreApplication.translate 135 | LCDCPickerDialog.setWindowTitle(_translate("LCDCPickerDialog", "PyWD2015")) 136 | self.groupBox.setTitle(_translate("LCDCPickerDialog", "Paths")) 137 | self.pickdc_btn.setText(_translate("LCDCPickerDialog", "Pick File")) 138 | self.label_68.setText(_translate("LCDCPickerDialog", "LC Binary:")) 139 | self.label_67.setText(_translate("LCDCPickerDialog", "DC Binary:")) 140 | self.picklc_btn.setText(_translate("LCDCPickerDialog", "Pick File")) 141 | self.groupBox_2.setTitle(_translate("LCDCPickerDialog", "Links")) 142 | self.label_65.setText(_translate("LCDCPickerDialog", "WD Homepage:")) 143 | self.lineEdit.setText(_translate("LCDCPickerDialog", "github.com/Varnani/PyWD2015")) 144 | self.label_66.setText(_translate("LCDCPickerDialog", "GitHub:")) 145 | self.lineEdit_2.setText(_translate("LCDCPickerDialog", "github.com/rewilsonufl/ebmodel")) 146 | self.label_2.setText(_translate("LCDCPickerDialog", "PyWD2015 is a GUI for 2015 version of LC and DC programs of Wilson - Devinney (WD) eclipsing binary modeling code. PyWD2015 needs these programs to function. Please provide their paths below.\n" 147 | "\n" 148 | "Precompiled WD binaries and associated limb darkening tables are hosted on GitHub release page with permissions of Dr. Robert E. Wilson and Dr. Walter Van Hamme. You can also obtain source codes and limb darkening tables from the WD Homepage and compile LC and DC codes yourself.")) 149 | self.label.setText(_translate("LCDCPickerDialog", "Welcome to PyWD2015")) 150 | self.save_btn.setText(_translate("LCDCPickerDialog", "Save")) 151 | self.exit_btn.setText(_translate("LCDCPickerDialog", "Exit")) 152 | 153 | -------------------------------------------------------------------------------- /gui/loadobservations_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'loadobservations_widget.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_ObservationWidget(object): 12 | def setupUi(self, ObservationWidget): 13 | ObservationWidget.setObjectName("ObservationWidget") 14 | ObservationWidget.resize(600, 250) 15 | ObservationWidget.setMinimumSize(QtCore.QSize(450, 200)) 16 | ObservationWidget.setMaximumSize(QtCore.QSize(900, 400)) 17 | self.gridLayout = QtWidgets.QGridLayout(ObservationWidget) 18 | self.gridLayout.setObjectName("gridLayout") 19 | self.plot_btn = QtWidgets.QPushButton(ObservationWidget) 20 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) 21 | sizePolicy.setHorizontalStretch(0) 22 | sizePolicy.setVerticalStretch(0) 23 | sizePolicy.setHeightForWidth(self.plot_btn.sizePolicy().hasHeightForWidth()) 24 | self.plot_btn.setSizePolicy(sizePolicy) 25 | self.plot_btn.setObjectName("plot_btn") 26 | self.gridLayout.addWidget(self.plot_btn, 5, 0, 1, 1) 27 | self.remove_btn = QtWidgets.QPushButton(ObservationWidget) 28 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) 29 | sizePolicy.setHorizontalStretch(0) 30 | sizePolicy.setVerticalStretch(0) 31 | sizePolicy.setHeightForWidth(self.remove_btn.sizePolicy().hasHeightForWidth()) 32 | self.remove_btn.setSizePolicy(sizePolicy) 33 | self.remove_btn.setObjectName("remove_btn") 34 | self.gridLayout.addWidget(self.remove_btn, 4, 0, 1, 1) 35 | self.edit_btn = QtWidgets.QPushButton(ObservationWidget) 36 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) 37 | sizePolicy.setHorizontalStretch(0) 38 | sizePolicy.setVerticalStretch(0) 39 | sizePolicy.setHeightForWidth(self.edit_btn.sizePolicy().hasHeightForWidth()) 40 | self.edit_btn.setSizePolicy(sizePolicy) 41 | self.edit_btn.setObjectName("edit_btn") 42 | self.gridLayout.addWidget(self.edit_btn, 3, 0, 1, 1) 43 | self.add_btn = QtWidgets.QPushButton(ObservationWidget) 44 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) 45 | sizePolicy.setHorizontalStretch(0) 46 | sizePolicy.setVerticalStretch(0) 47 | sizePolicy.setHeightForWidth(self.add_btn.sizePolicy().hasHeightForWidth()) 48 | self.add_btn.setSizePolicy(sizePolicy) 49 | self.add_btn.setObjectName("add_btn") 50 | self.gridLayout.addWidget(self.add_btn, 2, 0, 1, 1) 51 | self.line = QtWidgets.QFrame(ObservationWidget) 52 | self.line.setFrameShape(QtWidgets.QFrame.HLine) 53 | self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 54 | self.line.setObjectName("line") 55 | self.gridLayout.addWidget(self.line, 1, 0, 1, 3) 56 | self.label = QtWidgets.QLabel(ObservationWidget) 57 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 58 | sizePolicy.setHorizontalStretch(0) 59 | sizePolicy.setVerticalStretch(0) 60 | sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) 61 | self.label.setSizePolicy(sizePolicy) 62 | self.label.setObjectName("label") 63 | self.gridLayout.addWidget(self.label, 0, 0, 1, 3) 64 | self.line_2 = QtWidgets.QFrame(ObservationWidget) 65 | self.line_2.setFrameShape(QtWidgets.QFrame.VLine) 66 | self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) 67 | self.line_2.setObjectName("line_2") 68 | self.gridLayout.addWidget(self.line_2, 2, 1, 4, 1) 69 | self.curve_treewidget = QtWidgets.QTreeWidget(ObservationWidget) 70 | self.curve_treewidget.setFrameShape(QtWidgets.QFrame.StyledPanel) 71 | self.curve_treewidget.setIndentation(10) 72 | self.curve_treewidget.setExpandsOnDoubleClick(True) 73 | self.curve_treewidget.setObjectName("curve_treewidget") 74 | self.curve_treewidget.header().setDefaultSectionSize(100) 75 | self.curve_treewidget.header().setMinimumSectionSize(50) 76 | self.curve_treewidget.header().setStretchLastSection(True) 77 | self.gridLayout.addWidget(self.curve_treewidget, 2, 2, 4, 1) 78 | 79 | self.retranslateUi(ObservationWidget) 80 | QtCore.QMetaObject.connectSlotsByName(ObservationWidget) 81 | 82 | def retranslateUi(self, ObservationWidget): 83 | _translate = QtCore.QCoreApplication.translate 84 | ObservationWidget.setWindowTitle(_translate("ObservationWidget", "Load Observations")) 85 | self.plot_btn.setText(_translate("ObservationWidget", "Plot")) 86 | self.remove_btn.setText(_translate("ObservationWidget", "Remove")) 87 | self.edit_btn.setText(_translate("ObservationWidget", "Edit")) 88 | self.add_btn.setText(_translate("ObservationWidget", "Add")) 89 | self.label.setText(_translate("ObservationWidget", "Load or edit observations from files:")) 90 | self.curve_treewidget.headerItem().setText(0, _translate("ObservationWidget", "Filename")) 91 | self.curve_treewidget.headerItem().setText(1, _translate("ObservationWidget", "Type")) 92 | self.curve_treewidget.headerItem().setText(2, _translate("ObservationWidget", "Band")) 93 | 94 | -------------------------------------------------------------------------------- /gui/oc_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'oc_widget.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_OCWidget(object): 12 | def setupUi(self, OCWidget): 13 | OCWidget.setObjectName("OCWidget") 14 | OCWidget.resize(850, 500) 15 | OCWidget.setMinimumSize(QtCore.QSize(850, 500)) 16 | self.horizontalLayout = QtWidgets.QHBoxLayout(OCWidget) 17 | self.horizontalLayout.setObjectName("horizontalLayout") 18 | self.gridLayout = QtWidgets.QGridLayout() 19 | self.gridLayout.setObjectName("gridLayout") 20 | self.plot_widget = QtWidgets.QWidget(OCWidget) 21 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) 22 | sizePolicy.setHorizontalStretch(0) 23 | sizePolicy.setVerticalStretch(0) 24 | sizePolicy.setHeightForWidth(self.plot_widget.sizePolicy().hasHeightForWidth()) 25 | self.plot_widget.setSizePolicy(sizePolicy) 26 | self.plot_widget.setMinimumSize(QtCore.QSize(400, 300)) 27 | self.plot_widget.setObjectName("plot_widget") 28 | self.gridLayout.addWidget(self.plot_widget, 0, 3, 6, 1) 29 | self.line_2 = QtWidgets.QFrame(OCWidget) 30 | self.line_2.setFrameShape(QtWidgets.QFrame.VLine) 31 | self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) 32 | self.line_2.setObjectName("line_2") 33 | self.gridLayout.addWidget(self.line_2, 0, 2, 6, 1) 34 | self.groupBox = QtWidgets.QGroupBox(OCWidget) 35 | self.groupBox.setObjectName("groupBox") 36 | self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) 37 | self.gridLayout_2.setObjectName("gridLayout_2") 38 | self.label_2 = QtWidgets.QLabel(self.groupBox) 39 | self.label_2.setObjectName("label_2") 40 | self.gridLayout_2.addWidget(self.label_2, 1, 0, 1, 1) 41 | self.dt_otpt = QtWidgets.QDoubleSpinBox(self.groupBox) 42 | self.dt_otpt.setReadOnly(True) 43 | self.dt_otpt.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) 44 | self.dt_otpt.setDecimals(7) 45 | self.dt_otpt.setMinimum(-9999999.0) 46 | self.dt_otpt.setMaximum(9999999.0) 47 | self.dt_otpt.setObjectName("dt_otpt") 48 | self.gridLayout_2.addWidget(self.dt_otpt, 0, 1, 1, 1) 49 | self.dp_otpt = QtWidgets.QDoubleSpinBox(self.groupBox) 50 | self.dp_otpt.setReadOnly(True) 51 | self.dp_otpt.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) 52 | self.dp_otpt.setDecimals(10) 53 | self.dp_otpt.setMinimum(-9999999.0) 54 | self.dp_otpt.setMaximum(9999999.0) 55 | self.dp_otpt.setObjectName("dp_otpt") 56 | self.gridLayout_2.addWidget(self.dp_otpt, 1, 1, 1, 1) 57 | self.label = QtWidgets.QLabel(self.groupBox) 58 | self.label.setObjectName("label") 59 | self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1) 60 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout() 61 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 62 | self.calculate_btn = QtWidgets.QPushButton(self.groupBox) 63 | self.calculate_btn.setObjectName("calculate_btn") 64 | self.horizontalLayout_2.addWidget(self.calculate_btn) 65 | self.update_btn = QtWidgets.QPushButton(self.groupBox) 66 | self.update_btn.setObjectName("update_btn") 67 | self.horizontalLayout_2.addWidget(self.update_btn) 68 | self.gridLayout_2.addLayout(self.horizontalLayout_2, 4, 0, 1, 2) 69 | self.gridLayout.addWidget(self.groupBox, 5, 0, 1, 2) 70 | self.dpdt_chk = QtWidgets.QCheckBox(OCWidget) 71 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) 72 | sizePolicy.setHorizontalStretch(0) 73 | sizePolicy.setVerticalStretch(0) 74 | sizePolicy.setHeightForWidth(self.dpdt_chk.sizePolicy().hasHeightForWidth()) 75 | self.dpdt_chk.setSizePolicy(sizePolicy) 76 | self.dpdt_chk.setObjectName("dpdt_chk") 77 | self.gridLayout.addWidget(self.dpdt_chk, 2, 1, 1, 1) 78 | self.line = QtWidgets.QFrame(OCWidget) 79 | self.line.setFrameShape(QtWidgets.QFrame.HLine) 80 | self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 81 | self.line.setObjectName("line") 82 | self.gridLayout.addWidget(self.line, 3, 0, 1, 2) 83 | self.linear_chk = QtWidgets.QCheckBox(OCWidget) 84 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) 85 | sizePolicy.setHorizontalStretch(0) 86 | sizePolicy.setVerticalStretch(0) 87 | sizePolicy.setHeightForWidth(self.linear_chk.sizePolicy().hasHeightForWidth()) 88 | self.linear_chk.setSizePolicy(sizePolicy) 89 | self.linear_chk.setObjectName("linear_chk") 90 | self.gridLayout.addWidget(self.linear_chk, 2, 0, 1, 1) 91 | self.data_treewidget = QtWidgets.QTreeWidget(OCWidget) 92 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 93 | sizePolicy.setHorizontalStretch(0) 94 | sizePolicy.setVerticalStretch(0) 95 | sizePolicy.setHeightForWidth(self.data_treewidget.sizePolicy().hasHeightForWidth()) 96 | self.data_treewidget.setSizePolicy(sizePolicy) 97 | self.data_treewidget.setMinimumSize(QtCore.QSize(350, 0)) 98 | self.data_treewidget.setObjectName("data_treewidget") 99 | self.gridLayout.addWidget(self.data_treewidget, 4, 0, 1, 2) 100 | self.line_3 = QtWidgets.QFrame(OCWidget) 101 | self.line_3.setFrameShape(QtWidgets.QFrame.HLine) 102 | self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken) 103 | self.line_3.setObjectName("line_3") 104 | self.gridLayout.addWidget(self.line_3, 1, 0, 1, 2) 105 | self.compute_btn = QtWidgets.QPushButton(OCWidget) 106 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) 107 | sizePolicy.setHorizontalStretch(0) 108 | sizePolicy.setVerticalStretch(0) 109 | sizePolicy.setHeightForWidth(self.compute_btn.sizePolicy().hasHeightForWidth()) 110 | self.compute_btn.setSizePolicy(sizePolicy) 111 | self.compute_btn.setObjectName("compute_btn") 112 | self.gridLayout.addWidget(self.compute_btn, 0, 0, 1, 1) 113 | self.export_btn = QtWidgets.QPushButton(OCWidget) 114 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) 115 | sizePolicy.setHorizontalStretch(0) 116 | sizePolicy.setVerticalStretch(0) 117 | sizePolicy.setHeightForWidth(self.export_btn.sizePolicy().hasHeightForWidth()) 118 | self.export_btn.setSizePolicy(sizePolicy) 119 | self.export_btn.setObjectName("export_btn") 120 | self.gridLayout.addWidget(self.export_btn, 0, 1, 1, 1) 121 | self.horizontalLayout.addLayout(self.gridLayout) 122 | 123 | self.retranslateUi(OCWidget) 124 | QtCore.QMetaObject.connectSlotsByName(OCWidget) 125 | 126 | def retranslateUi(self, OCWidget): 127 | _translate = QtCore.QCoreApplication.translate 128 | OCWidget.setWindowTitle(_translate("OCWidget", "Compute O - C")) 129 | self.groupBox.setTitle(_translate("OCWidget", "Epoch and Period Correction")) 130 | self.label_2.setText(_translate("OCWidget", "ΔP")) 131 | self.label.setText(_translate("OCWidget", "ΔT")) 132 | self.calculate_btn.setText(_translate("OCWidget", "Calculate")) 133 | self.update_btn.setText(_translate("OCWidget", "Update")) 134 | self.dpdt_chk.setText(_translate("OCWidget", "Residuals with dP/dt")) 135 | self.linear_chk.setText(_translate("OCWidget", "Linear Residuals")) 136 | self.data_treewidget.headerItem().setText(0, _translate("OCWidget", "HJD")) 137 | self.data_treewidget.headerItem().setText(1, _translate("OCWidget", "Lin. Res.")) 138 | self.data_treewidget.headerItem().setToolTip(1, _translate("OCWidget", "Linear residuals")) 139 | self.data_treewidget.headerItem().setText(2, _translate("OCWidget", "with dP/dt")) 140 | self.data_treewidget.headerItem().setToolTip(2, _translate("OCWidget", "Linear residuals with dP/dt")) 141 | self.compute_btn.setText(_translate("OCWidget", "Compute")) 142 | self.export_btn.setText(_translate("OCWidget", "Export")) 143 | 144 | 145 | if __name__ == "__main__": 146 | import sys 147 | app = QtWidgets.QApplication(sys.argv) 148 | OCWidget = QtWidgets.QWidget() 149 | ui = Ui_OCWidget() 150 | ui.setupUi(OCWidget) 151 | OCWidget.show() 152 | sys.exit(app.exec_()) 153 | 154 | -------------------------------------------------------------------------------- /gui/outputview_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'outputview_widget.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_OutputView(object): 12 | def setupUi(self, OutputView): 13 | OutputView.setObjectName("OutputView") 14 | OutputView.resize(900, 500) 15 | OutputView.setMinimumSize(QtCore.QSize(500, 250)) 16 | self.gridLayout = QtWidgets.QGridLayout(OutputView) 17 | self.gridLayout.setObjectName("gridLayout") 18 | self.jmp_beginning_btn = QtWidgets.QPushButton(OutputView) 19 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 20 | sizePolicy.setHorizontalStretch(0) 21 | sizePolicy.setVerticalStretch(0) 22 | sizePolicy.setHeightForWidth(self.jmp_beginning_btn.sizePolicy().hasHeightForWidth()) 23 | self.jmp_beginning_btn.setSizePolicy(sizePolicy) 24 | self.jmp_beginning_btn.setObjectName("jmp_beginning_btn") 25 | self.gridLayout.addWidget(self.jmp_beginning_btn, 0, 0, 1, 1) 26 | self.jmp_end_btn = QtWidgets.QPushButton(OutputView) 27 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 28 | sizePolicy.setHorizontalStretch(0) 29 | sizePolicy.setVerticalStretch(0) 30 | sizePolicy.setHeightForWidth(self.jmp_end_btn.sizePolicy().hasHeightForWidth()) 31 | self.jmp_end_btn.setSizePolicy(sizePolicy) 32 | self.jmp_end_btn.setObjectName("jmp_end_btn") 33 | self.gridLayout.addWidget(self.jmp_end_btn, 0, 1, 1, 1) 34 | self.horizontalLayout = QtWidgets.QHBoxLayout() 35 | self.horizontalLayout.setObjectName("horizontalLayout") 36 | self.jmp_text_btn = QtWidgets.QPushButton(OutputView) 37 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 38 | sizePolicy.setHorizontalStretch(0) 39 | sizePolicy.setVerticalStretch(0) 40 | sizePolicy.setHeightForWidth(self.jmp_text_btn.sizePolicy().hasHeightForWidth()) 41 | self.jmp_text_btn.setSizePolicy(sizePolicy) 42 | self.jmp_text_btn.setObjectName("jmp_text_btn") 43 | self.horizontalLayout.addWidget(self.jmp_text_btn) 44 | self.jmp_text_tipt = QtWidgets.QLineEdit(OutputView) 45 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 46 | sizePolicy.setHorizontalStretch(0) 47 | sizePolicy.setVerticalStretch(0) 48 | sizePolicy.setHeightForWidth(self.jmp_text_tipt.sizePolicy().hasHeightForWidth()) 49 | self.jmp_text_tipt.setSizePolicy(sizePolicy) 50 | self.jmp_text_tipt.setObjectName("jmp_text_tipt") 51 | self.horizontalLayout.addWidget(self.jmp_text_tipt) 52 | self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 2) 53 | self.output_textedit = QtWidgets.QPlainTextEdit(OutputView) 54 | self.output_textedit.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) 55 | self.output_textedit.setReadOnly(True) 56 | self.output_textedit.setObjectName("output_textedit") 57 | self.gridLayout.addWidget(self.output_textedit, 2, 0, 1, 2) 58 | 59 | self.retranslateUi(OutputView) 60 | QtCore.QMetaObject.connectSlotsByName(OutputView) 61 | 62 | def retranslateUi(self, OutputView): 63 | _translate = QtCore.QCoreApplication.translate 64 | OutputView.setWindowTitle(_translate("OutputView", "///")) 65 | self.jmp_beginning_btn.setText(_translate("OutputView", "Jump to Beginning")) 66 | self.jmp_end_btn.setText(_translate("OutputView", "Jump to End")) 67 | self.jmp_text_btn.setText(_translate("OutputView", "Jump to Line Containing Text:")) 68 | 69 | -------------------------------------------------------------------------------- /gui/single_conjunction.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'single_conjunction.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.11.3 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_ConjunctionWidget(object): 12 | def setupUi(self, ConjunctionWidget): 13 | ConjunctionWidget.setObjectName("ConjunctionWidget") 14 | ConjunctionWidget.resize(500, 220) 15 | ConjunctionWidget.setMinimumSize(QtCore.QSize(500, 220)) 16 | ConjunctionWidget.setMaximumSize(QtCore.QSize(500, 220)) 17 | self.gridLayout = QtWidgets.QGridLayout(ConjunctionWidget) 18 | self.gridLayout.setObjectName("gridLayout") 19 | self.groupBox = QtWidgets.QGroupBox(ConjunctionWidget) 20 | self.groupBox.setObjectName("groupBox") 21 | self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox) 22 | self.gridLayout_2.setObjectName("gridLayout_2") 23 | self.primary_label = QtWidgets.QLabel(self.groupBox) 24 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 25 | sizePolicy.setHorizontalStretch(0) 26 | sizePolicy.setVerticalStretch(0) 27 | sizePolicy.setHeightForWidth(self.primary_label.sizePolicy().hasHeightForWidth()) 28 | self.primary_label.setSizePolicy(sizePolicy) 29 | self.primary_label.setObjectName("primary_label") 30 | self.gridLayout_2.addWidget(self.primary_label, 0, 0, 1, 1) 31 | self.f_quadrature_label = QtWidgets.QLabel(self.groupBox) 32 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 33 | sizePolicy.setHorizontalStretch(0) 34 | sizePolicy.setVerticalStretch(0) 35 | sizePolicy.setHeightForWidth(self.f_quadrature_label.sizePolicy().hasHeightForWidth()) 36 | self.f_quadrature_label.setSizePolicy(sizePolicy) 37 | self.f_quadrature_label.setObjectName("f_quadrature_label") 38 | self.gridLayout_2.addWidget(self.f_quadrature_label, 0, 1, 1, 1) 39 | self.p_ast_label = QtWidgets.QLabel(self.groupBox) 40 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 41 | sizePolicy.setHorizontalStretch(0) 42 | sizePolicy.setVerticalStretch(0) 43 | sizePolicy.setHeightForWidth(self.p_ast_label.sizePolicy().hasHeightForWidth()) 44 | self.p_ast_label.setSizePolicy(sizePolicy) 45 | self.p_ast_label.setObjectName("p_ast_label") 46 | self.gridLayout_2.addWidget(self.p_ast_label, 0, 2, 1, 1) 47 | self.horizontalLayout = QtWidgets.QHBoxLayout() 48 | self.horizontalLayout.setObjectName("horizontalLayout") 49 | self.prieclipse_opt = QtWidgets.QLineEdit(self.groupBox) 50 | self.prieclipse_opt.setReadOnly(True) 51 | self.prieclipse_opt.setObjectName("prieclipse_opt") 52 | self.horizontalLayout.addWidget(self.prieclipse_opt) 53 | self.firstquad_opt = QtWidgets.QLineEdit(self.groupBox) 54 | self.firstquad_opt.setReadOnly(True) 55 | self.firstquad_opt.setObjectName("firstquad_opt") 56 | self.horizontalLayout.addWidget(self.firstquad_opt) 57 | self.periastron_opt = QtWidgets.QLineEdit(self.groupBox) 58 | self.periastron_opt.setReadOnly(True) 59 | self.periastron_opt.setObjectName("periastron_opt") 60 | self.horizontalLayout.addWidget(self.periastron_opt) 61 | self.gridLayout_2.addLayout(self.horizontalLayout, 1, 0, 1, 3) 62 | self.s_eclipse_label = QtWidgets.QLabel(self.groupBox) 63 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 64 | sizePolicy.setHorizontalStretch(0) 65 | sizePolicy.setVerticalStretch(0) 66 | sizePolicy.setHeightForWidth(self.s_eclipse_label.sizePolicy().hasHeightForWidth()) 67 | self.s_eclipse_label.setSizePolicy(sizePolicy) 68 | self.s_eclipse_label.setObjectName("s_eclipse_label") 69 | self.gridLayout_2.addWidget(self.s_eclipse_label, 2, 0, 1, 1) 70 | self.secondary_label = QtWidgets.QLabel(self.groupBox) 71 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 72 | sizePolicy.setHorizontalStretch(0) 73 | sizePolicy.setVerticalStretch(0) 74 | sizePolicy.setHeightForWidth(self.secondary_label.sizePolicy().hasHeightForWidth()) 75 | self.secondary_label.setSizePolicy(sizePolicy) 76 | self.secondary_label.setObjectName("secondary_label") 77 | self.gridLayout_2.addWidget(self.secondary_label, 2, 1, 1, 1) 78 | self.a_past_label = QtWidgets.QLabel(self.groupBox) 79 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 80 | sizePolicy.setHorizontalStretch(0) 81 | sizePolicy.setVerticalStretch(0) 82 | sizePolicy.setHeightForWidth(self.a_past_label.sizePolicy().hasHeightForWidth()) 83 | self.a_past_label.setSizePolicy(sizePolicy) 84 | self.a_past_label.setObjectName("a_past_label") 85 | self.gridLayout_2.addWidget(self.a_past_label, 2, 2, 1, 1) 86 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout() 87 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 88 | self.sececlipse_opt = QtWidgets.QLineEdit(self.groupBox) 89 | self.sececlipse_opt.setReadOnly(True) 90 | self.sececlipse_opt.setObjectName("sececlipse_opt") 91 | self.horizontalLayout_2.addWidget(self.sececlipse_opt) 92 | self.secondquad_opt = QtWidgets.QLineEdit(self.groupBox) 93 | self.secondquad_opt.setReadOnly(True) 94 | self.secondquad_opt.setObjectName("secondquad_opt") 95 | self.horizontalLayout_2.addWidget(self.secondquad_opt) 96 | self.apastron_opt = QtWidgets.QLineEdit(self.groupBox) 97 | self.apastron_opt.setReadOnly(True) 98 | self.apastron_opt.setObjectName("apastron_opt") 99 | self.horizontalLayout_2.addWidget(self.apastron_opt) 100 | self.gridLayout_2.addLayout(self.horizontalLayout_2, 3, 0, 1, 3) 101 | self.conj_btn = QtWidgets.QPushButton(self.groupBox) 102 | self.conj_btn.setObjectName("conj_btn") 103 | self.gridLayout_2.addWidget(self.conj_btn, 4, 0, 1, 3) 104 | self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1) 105 | 106 | self.retranslateUi(ConjunctionWidget) 107 | QtCore.QMetaObject.connectSlotsByName(ConjunctionWidget) 108 | ConjunctionWidget.setTabOrder(self.prieclipse_opt, self.firstquad_opt) 109 | ConjunctionWidget.setTabOrder(self.firstquad_opt, self.periastron_opt) 110 | ConjunctionWidget.setTabOrder(self.periastron_opt, self.sececlipse_opt) 111 | ConjunctionWidget.setTabOrder(self.sececlipse_opt, self.secondquad_opt) 112 | ConjunctionWidget.setTabOrder(self.secondquad_opt, self.apastron_opt) 113 | ConjunctionWidget.setTabOrder(self.apastron_opt, self.conj_btn) 114 | 115 | def retranslateUi(self, ConjunctionWidget): 116 | _translate = QtCore.QCoreApplication.translate 117 | ConjunctionWidget.setWindowTitle(_translate("ConjunctionWidget", "Computed Conjunctions")) 118 | self.groupBox.setTitle(_translate("ConjunctionWidget", "Conjunction Phases")) 119 | self.primary_label.setText(_translate("ConjunctionWidget", "Primary Eclipse")) 120 | self.f_quadrature_label.setText(_translate("ConjunctionWidget", "First Quadrature")) 121 | self.p_ast_label.setText(_translate("ConjunctionWidget", "Periastron")) 122 | self.s_eclipse_label.setText(_translate("ConjunctionWidget", "Secondary Eclipse")) 123 | self.secondary_label.setText(_translate("ConjunctionWidget", "Second Quadrature")) 124 | self.a_past_label.setText(_translate("ConjunctionWidget", "Apastron")) 125 | self.conj_btn.setText(_translate("ConjunctionWidget", "Compute Conjunction Phases")) 126 | 127 | 128 | if __name__ == "__main__": 129 | import sys 130 | app = QtWidgets.QApplication(sys.argv) 131 | ConjunctionWidget = QtWidgets.QWidget() 132 | ui = Ui_ConjunctionWidget() 133 | ui.setupUi(ConjunctionWidget) 134 | ConjunctionWidget.show() 135 | sys.exit(app.exec_()) 136 | 137 | -------------------------------------------------------------------------------- /pywd2015.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import sys 3 | from PyQt5 import QtWidgets 4 | from src.interfaces import mainwindow_interface 5 | 6 | 7 | def run(): 8 | if platform.system() == "Windows": # used for making app icon visible in windows taskbar 9 | import ctypes 10 | appid = "pywd2015-qt5" 11 | ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(appid) 12 | app = QtWidgets.QApplication(sys.argv) 13 | gui = mainwindow_interface.Widget(app) 14 | if gui.start_up(): 15 | gui.show() 16 | sys.exit(app.exec_()) 17 | else: 18 | return 0 19 | 20 | 21 | if __name__ == "__main__": 22 | run() 23 | -------------------------------------------------------------------------------- /resources/PTM55FT-OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, ParaType Ltd. (http://www.paratype.com/public), 2 | with Reserved Font Names "PT Sans", "PT Serif", "PT Mono" and "ParaType". 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | 96 | -------------------------------------------------------------------------------- /resources/PTM55FT.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/resources/PTM55FT.ttf -------------------------------------------------------------------------------- /resources/configurespots_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SpotConfigureWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 900 10 | 650 11 | 12 | 13 | 14 | 15 | 900 16 | 650 17 | 18 | 19 | 20 | Configure Spots 21 | 22 | 23 | 24 | 25 | 26 | Qt::Vertical 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 0 35 | 0 36 | 37 | 38 | 39 | Load Spots 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 0 48 | 0 49 | 50 | 51 | 52 | 53 | 75 54 | true 55 | 56 | 57 | 58 | ? 59 | 60 | 61 | 62 | 63 | 64 | 65 | <html><head/><body><p>Enable spot aging (KSPEV) [?]</p></body></html> 66 | 67 | 68 | <html><head/><body><p>Controls whether spots age (grow and decay) in radius. Currently there is no aging in spot temperature. Uncheck for no aging, check for aging. Solutions for spot aging need good starting estimates for spot parameters and careful monitoring of solution progress.</p></body></html> 69 | 70 | 71 | Spo&t Aging 72 | 73 | 74 | true 75 | 76 | 77 | 78 | 79 | 80 | <html><head/><body><p>Spot aging profile (NOMAX) [?]</p></body></html> 81 | 82 | 83 | <html><head/><body><p>Tells whether the spot growth and decay timewise profile is trapezoidal or triangular. Setting this to triangular eliminates the interval of constant size that otherwise exists at spot maximum.</p></body></html> 84 | 85 | 86 | Aging Profile 87 | 88 | 89 | 90 | 91 | 92 | 93 | <html><head/><body><p>Spot aging profile (Triangular-NOMAX=1; or Trapezoidal-NOMAX=0) [?]</p></body></html> 94 | 95 | 96 | 97 | Triangular 98 | 99 | 100 | 101 | 102 | Trapezoidal 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | Qt::Horizontal 114 | 115 | 116 | 117 | 118 | 119 | 120 | Qt::Vertical 121 | 122 | 123 | 124 | 125 | 126 | 127 | <html><head/><body><p>Spot angular drift rate in longitude for star 1 and 2, rate 1.000 means that drift matches the mean orbital angular rate (Fspot1, Fspot2)</p></body></html> 128 | 129 | 130 | Drift Rates 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | Star 1 140 | 141 | 142 | 143 | 144 | 145 | 146 | QAbstractSpinBox::NoButtons 147 | 148 | 149 | 4 150 | 151 | 152 | 99.000000000000000 153 | 154 | 155 | 1.000000000000000 156 | 157 | 158 | 1.000000000000000 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | Star 2 169 | 170 | 171 | 172 | 173 | 174 | 175 | QAbstractSpinBox::NoButtons 176 | 177 | 178 | 4 179 | 180 | 181 | 99.000000000000000 182 | 183 | 184 | 1.000000000000000 185 | 186 | 187 | 1.000000000000000 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | Star 2 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 0 206 | 0 207 | 208 | 209 | 210 | Save Spots 211 | 212 | 213 | 214 | 215 | 216 | 217 | Qt::Vertical 218 | 219 | 220 | 221 | 222 | 223 | 224 | Spot Movement 225 | 226 | 227 | 228 | 229 | 230 | <html><head/><body><p>Allow spot A to move in longitude (IFSMV1)</p></body></html> 231 | 232 | 233 | Allow for Spot A 234 | 235 | 236 | 237 | 238 | 239 | 240 | <html><head/><body><p>Allow spot B to move in longitude (IFSMV2)</p></body></html> 241 | 242 | 243 | Allow for Spot B 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 0 255 | 0 256 | 257 | 258 | 259 | Add spots and configure spot related parameters 260 | 261 | 262 | 263 | 264 | 265 | 266 | Qt::Horizontal 267 | 268 | 269 | 270 | 271 | 272 | 273 | Star 1 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | <html><head/><body><p>Use &quot;Vector Fractional Area&quot; algorithm (KSPOT) [?]</p></body></html> 283 | 284 | 285 | <html><head/><body><p>Controls whether the old simple spot algorithm or the much more precise Vector Fractional Area algorithm <span style=" font-weight:600;">(Wilson 2012b)</span> is applied.</p></body></html> 286 | 287 | 288 | Use "VFA" 289 | 290 | 291 | 292 | 293 | 294 | 295 | Qt::Horizontal 296 | 297 | 298 | 299 | 300 | 301 | 302 | Clear A and B 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | -------------------------------------------------------------------------------- /resources/conjunction_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | conjunctionwidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 450 10 | 700 11 | 12 | 13 | 14 | 15 | 450 16 | 500 17 | 18 | 19 | 20 | 21 | 600 22 | 1000 23 | 24 | 25 | 26 | Compute Conjunction Times 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Space conjunction times by a whole orbit cycles per minima [KTSTEP] 35 | 36 | 37 | Cycle Step 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | Compute &UTC 48 | 49 | 50 | false 51 | 52 | 53 | true 54 | 55 | 56 | true 57 | 58 | 59 | 60 | 61 | 62 | false 63 | 64 | 65 | 66 | 0 67 | 68 | 69 | 0 70 | 71 | 72 | 0 73 | 74 | 75 | 0 76 | 77 | 78 | 0 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | Convert HJD &to JD 87 | 88 | 89 | true 90 | 91 | 92 | true 93 | 94 | 95 | false 96 | 97 | 98 | 99 | 100 | 101 | 10 102 | 103 | 104 | 5 105 | 106 | 107 | 108 | 109 | Right Ascension 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 0 118 | 0 119 | 120 | 121 | 122 | ° 123 | 124 | 125 | 126 | 127 | 128 | 129 | 59 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 0 138 | 0 139 | 140 | 141 | 142 | " 143 | 144 | 145 | 146 | 147 | 148 | 149 | -90 150 | 151 | 152 | 90 153 | 154 | 155 | 156 | 157 | 158 | 159 | 59 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 0 168 | 0 169 | 170 | 171 | 172 | Second 173 | 174 | 175 | 176 | 177 | 178 | 179 | Declination 180 | 181 | 182 | 183 | 184 | 185 | 186 | 59 187 | 188 | 189 | 190 | 191 | 192 | 193 | 23 194 | 195 | 196 | 197 | 198 | 199 | 200 | 59 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 0 209 | 0 210 | 211 | 212 | 213 | ' 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 0 222 | 0 223 | 224 | 225 | 226 | Minute 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 0 235 | 0 236 | 237 | 238 | 239 | Hour 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | Qt::Horizontal 255 | 256 | 257 | 258 | 259 | 260 | 261 | Export 262 | 263 | 264 | 265 | 266 | 267 | 268 | Compute 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | HJD 277 | 278 | 279 | 280 | 281 | Min 282 | 283 | 284 | 285 | 286 | D/M/Y - H:M:S 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | Qt::Horizontal 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 0 303 | 0 304 | 305 | 306 | 307 | 1 308 | 309 | 310 | 99999 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | ra_h_spinbox 320 | ra_m_spinbox 321 | ra_s_spinbox 322 | dec_d_spinbox 323 | dec_m_spinbox 324 | dec_s_spinbox 325 | ut_groupbox 326 | dt_groupbox 327 | export_btn 328 | compute_btn 329 | data_treewidget 330 | kstep_spinbox 331 | 332 | 333 | 334 | 335 | -------------------------------------------------------------------------------- /resources/eclipsetimings_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | EclipseWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 375 10 | 600 11 | 12 | 13 | 14 | 15 | 375 16 | 600 17 | 18 | 19 | 20 | 21 | 400 22 | 900 23 | 24 | 25 | 26 | Eclipse Timings 27 | 28 | 29 | 30 | 31 | 32 | Set standard deviation apply method. [?] 33 | 34 | 35 | <html><head/><body><p>An integer array that is 0, 1, or 2 for each input sub-dataset (velocity, light, or eclipse timings). </p><p>The KSDs tell DC whether to apply the input standard deviations (σ’s) to compute curvedependent weights (KSD=0), </p><p>to apply DC’s internally computed σ’s for the weights (KSD=1),</p><p>or to apply σ’s based on one or two restricted phase ranges for the weights (KSD=2).</p><p><span style=" font-weight:600;">If unsure, set to 1.</span></p></body></html> 36 | 37 | 38 | KSD 39 | 40 | 41 | 42 | 43 | 44 | 45 | QAbstractSpinBox::UpDownArrows 46 | 47 | 48 | 0 49 | 50 | 51 | 2 52 | 53 | 54 | 1 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Time 63 | 64 | 65 | 66 | 67 | Eclipse Type 68 | 69 | 70 | 71 | 72 | Weight 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Estimated standard deviation of observed light 81 | 82 | 83 | SIGMA 84 | 85 | 86 | 87 | 88 | 89 | 90 | Data preview of file: 91 | 92 | 93 | 94 | 95 | 96 | 97 | <html><head/><body><p>If checked, third column will be ignored and all weights will be assumed as unity.</p><p>If there isn't a third column, program will fill weights with unity too, regardless of this option.</p></body></html> 98 | 99 | 100 | Use constant weights (1.0) 101 | 102 | 103 | 104 | 105 | 106 | 107 | None 108 | 109 | 110 | 111 | 112 | 113 | 114 | Qt::Horizontal 115 | 116 | 117 | 118 | 119 | 120 | 121 | Qt::Horizontal 122 | 123 | 124 | 125 | 126 | 127 | 128 | Qt::Horizontal 129 | 130 | 131 | 132 | 133 | 134 | 135 | Load eclipse timings from a file 136 | 137 | 138 | 139 | 140 | 141 | 142 | Qt::Vertical 143 | 144 | 145 | 146 | 147 | 148 | 149 | IFTIME - Write eclipse timings 150 | 151 | 152 | 153 | 154 | 155 | 156 | Load 157 | 158 | 159 | 160 | 161 | 162 | 163 | Clear 164 | 165 | 166 | 167 | 168 | 169 | 170 | QAbstractSpinBox::NoButtons 171 | 172 | 173 | 8 174 | 175 | 176 | 99999.000000000000000 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /resources/history_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | HistoryWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 900 10 | 500 11 | 12 | 13 | 14 | Solution History 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Plot 25 | 26 | 27 | 28 | 29 | 30 | 31 | Automatically plot selected parameter when DC program finishes its calculation 32 | 33 | 34 | Auto 35 | 36 | 37 | 38 | 39 | 40 | 41 | Clear 42 | 43 | 44 | 45 | 46 | 47 | 48 | Export All 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 0 59 | 0 60 | 61 | 62 | 63 | 64 | 400 65 | 0 66 | 67 | 68 | 69 | QAbstractItemView::SelectColumns 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | Qt::Horizontal 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 0 90 | 0 91 | 92 | 93 | 94 | 95 | 300 96 | 300 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | Qt::Vertical 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /resources/lcdcpicker_dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LCDCPickerDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 700 10 | 500 11 | 12 | 13 | 14 | 15 | 700 16 | 500 17 | 18 | 19 | 20 | 21 | 700 22 | 500 23 | 24 | 25 | 26 | PyWD2015 27 | 28 | 29 | 30 | 31 | 32 | Paths 33 | 34 | 35 | 36 | 37 | 38 | Pick File 39 | 40 | 41 | 42 | 43 | 44 | 45 | LC Binary: 46 | 47 | 48 | 49 | 50 | 51 | 52 | DC Binary: 53 | 54 | 55 | 56 | 57 | 58 | 59 | Pick File 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 0 68 | 0 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 0 81 | 0 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | Links 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | WD Homepage: 104 | 105 | 106 | 107 | 108 | 109 | 110 | github.com/Varnani/PyWD2015 111 | 112 | 113 | true 114 | 115 | 116 | 117 | 118 | 119 | 120 | GitHub: 121 | 122 | 123 | 124 | 125 | 126 | 127 | github.com/rewilsonufl/ebmodel 128 | 129 | 130 | true 131 | 132 | 133 | 134 | 135 | 136 | 137 | Qt::Horizontal 138 | 139 | 140 | 141 | 40 142 | 20 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | Qt::Horizontal 151 | 152 | 153 | 154 | 40 155 | 20 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | Qt::Horizontal 169 | 170 | 171 | 172 | 173 | 174 | 175 | PyWD2015 is a GUI for 2015 version of LC and DC programs of Wilson - Devinney (WD) eclipsing binary modeling code. PyWD2015 needs these programs to function. Please provide their paths below. 176 | 177 | Precompiled WD binaries and associated limb darkening tables are hosted on GitHub release page with permissions of Dr. Robert E. Wilson and Dr. Walter Van Hamme. You can also obtain source codes and limb darkening tables from the WD Homepage and compile LC and DC codes yourself. 178 | 179 | 180 | Qt::PlainText 181 | 182 | 183 | false 184 | 185 | 186 | Qt::AlignJustify|Qt::AlignTop 187 | 188 | 189 | true 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 0 198 | 0 199 | 200 | 201 | 202 | 203 | 15 204 | 75 205 | true 206 | 207 | 208 | 209 | Welcome to PyWD2015 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 0 220 | 0 221 | 222 | 223 | 224 | Save 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 0 233 | 0 234 | 235 | 236 | 237 | Exit 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | Qt::Horizontal 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /resources/loadobservations_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ObservationWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 600 10 | 250 11 | 12 | 13 | 14 | 15 | 450 16 | 200 17 | 18 | 19 | 20 | 21 | 900 22 | 400 23 | 24 | 25 | 26 | Load Observations 27 | 28 | 29 | 30 | 31 | 32 | 33 | 0 34 | 0 35 | 36 | 37 | 38 | Plot 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 0 47 | 0 48 | 49 | 50 | 51 | Remove 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 0 60 | 0 61 | 62 | 63 | 64 | Edit 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 0 73 | 0 74 | 75 | 76 | 77 | Add 78 | 79 | 80 | 81 | 82 | 83 | 84 | Qt::Horizontal 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 0 93 | 0 94 | 95 | 96 | 97 | Load or edit observations from files: 98 | 99 | 100 | 101 | 102 | 103 | 104 | Qt::Vertical 105 | 106 | 107 | 108 | 109 | 110 | 111 | QFrame::StyledPanel 112 | 113 | 114 | 10 115 | 116 | 117 | true 118 | 119 | 120 | 100 121 | 122 | 123 | 50 124 | 125 | 126 | true 127 | 128 | 129 | 130 | Filename 131 | 132 | 133 | 134 | 135 | Type 136 | 137 | 138 | 139 | 140 | Band 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /resources/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/resources/next.png -------------------------------------------------------------------------------- /resources/oc_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | OCWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 850 10 | 500 11 | 12 | 13 | 14 | 15 | 850 16 | 500 17 | 18 | 19 | 20 | Compute O - C 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 0 30 | 0 31 | 32 | 33 | 34 | 35 | 400 36 | 300 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Qt::Vertical 45 | 46 | 47 | 48 | 49 | 50 | 51 | Epoch and Period Correction 52 | 53 | 54 | 55 | 56 | 57 | ΔP 58 | 59 | 60 | 61 | 62 | 63 | 64 | true 65 | 66 | 67 | QAbstractSpinBox::NoButtons 68 | 69 | 70 | 7 71 | 72 | 73 | -9999999.000000000000000 74 | 75 | 76 | 9999999.000000000000000 77 | 78 | 79 | 80 | 81 | 82 | 83 | true 84 | 85 | 86 | QAbstractSpinBox::NoButtons 87 | 88 | 89 | 10 90 | 91 | 92 | -9999999.000000000000000 93 | 94 | 95 | 9999999.000000000000000 96 | 97 | 98 | 99 | 100 | 101 | 102 | ΔT 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | Calculate 112 | 113 | 114 | 115 | 116 | 117 | 118 | Update 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 0 132 | 0 133 | 134 | 135 | 136 | Residuals with dP/dt 137 | 138 | 139 | 140 | 141 | 142 | 143 | Qt::Horizontal 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 0 152 | 0 153 | 154 | 155 | 156 | Linear Residuals 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 0 165 | 0 166 | 167 | 168 | 169 | 170 | 350 171 | 0 172 | 173 | 174 | 175 | 176 | HJD 177 | 178 | 179 | 180 | 181 | Lin. Res. 182 | 183 | 184 | Linear residuals 185 | 186 | 187 | 188 | 189 | with dP/dt 190 | 191 | 192 | Linear residuals with dP/dt 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | Qt::Horizontal 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 0 209 | 0 210 | 211 | 212 | 213 | Compute 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 0 222 | 0 223 | 224 | 225 | 226 | Export 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /resources/outputview_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | OutputView 4 | 5 | 6 | 7 | 0 8 | 0 9 | 900 10 | 500 11 | 12 | 13 | 14 | 15 | 500 16 | 250 17 | 18 | 19 | 20 | /// 21 | 22 | 23 | 24 | 25 | 26 | 27 | 0 28 | 0 29 | 30 | 31 | 32 | Jump to Beginning 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 0 41 | 0 42 | 43 | 44 | 45 | Jump to End 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 0 56 | 0 57 | 58 | 59 | 60 | Jump to Line Containing Text: 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 0 69 | 0 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | QPlainTextEdit::NoWrap 80 | 81 | 82 | true 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /resources/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/resources/pause.png -------------------------------------------------------------------------------- /resources/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/resources/play.png -------------------------------------------------------------------------------- /resources/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/resources/prev.png -------------------------------------------------------------------------------- /resources/pywd.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/resources/pywd.ico -------------------------------------------------------------------------------- /resources/single_conjunction.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ConjunctionWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 500 10 | 220 11 | 12 | 13 | 14 | 15 | 500 16 | 220 17 | 18 | 19 | 20 | 21 | 500 22 | 220 23 | 24 | 25 | 26 | Computed Conjunctions 27 | 28 | 29 | 30 | 31 | 32 | Conjunction Phases 33 | 34 | 35 | 36 | 37 | 38 | 39 | 0 40 | 0 41 | 42 | 43 | 44 | Primary Eclipse 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 0 53 | 0 54 | 55 | 56 | 57 | First Quadrature 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 0 66 | 0 67 | 68 | 69 | 70 | Periastron 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | true 80 | 81 | 82 | 83 | 84 | 85 | 86 | true 87 | 88 | 89 | 90 | 91 | 92 | 93 | true 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 0 104 | 0 105 | 106 | 107 | 108 | Secondary Eclipse 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 0 117 | 0 118 | 119 | 120 | 121 | Second Quadrature 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 0 130 | 0 131 | 132 | 133 | 134 | Apastron 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | true 144 | 145 | 146 | 147 | 148 | 149 | 150 | true 151 | 152 | 153 | 154 | 155 | 156 | 157 | true 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Compute Conjunction Phases 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | prieclipse_opt 177 | firstquad_opt 178 | periastron_opt 179 | sececlipse_opt 180 | secondquad_opt 181 | apastron_opt 182 | conj_btn 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/src/__init__.py -------------------------------------------------------------------------------- /src/constants.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | import os 3 | 4 | 5 | # info 6 | MAIN_VERSION = "2015-qt5" 7 | CONFIG_VERSION = "0.2.0" 8 | EXPORT_DELIMITER = "\t" 9 | 10 | # paths 11 | MAIN_DIR = os.path.dirname(os.path.abspath(inspect.stack()[-1][1])) # script dir 12 | PYWD_CONFIG_PATH = os.path.join(MAIN_DIR, "pywd_config.dat") 13 | RESOURCES_DIR = os.path.join(MAIN_DIR, "resources") 14 | MAIN_ICON_PATH = os.path.join(RESOURCES_DIR, "pywd.ico") 15 | PLAY_ICON_PATH = os.path.join(RESOURCES_DIR, "play.png") 16 | PAUSE_ICON_PATH = os.path.join(RESOURCES_DIR, "pause.png") 17 | NEXT_ICON_PATH = os.path.join(RESOURCES_DIR, "next.png") 18 | PREV_ICON_PATH = os.path.join(RESOURCES_DIR, "prev.png") 19 | MONO_FONT_PATH = os.path.join(RESOURCES_DIR, "PTM55FT.ttf") 20 | 21 | # hex colors and plot details 22 | MARKER_SIZE = 3 23 | COLOR_BLUE = "#4286f4" 24 | COLOR_RED = "#f5425a" 25 | COLOR_GREEN = "#2aa34b" 26 | COLOR_ORANGE = "#f5a142" 27 | DC_RESULTS_FONTSIZE = 9 28 | 29 | # config sections 30 | CONFIG_SECTION_INFO = "Info" 31 | CONFIG_SECTION_MAIN = "Main" 32 | CONFIG_SECTION_SYSTEM = "System" 33 | CONFIG_SECTION_SURFACE = "Surface" 34 | CONFIG_SECTION_3B = "Third_body" 35 | CONFIG_SECTION_LC2015 = "LC2015" 36 | CONFIG_SECTION_DC2015 = "DC2015" 37 | CONFIG_SECTION_KEEPS = "DC Keeps" 38 | CONFIG_SECTION_DELS = "DC Dels" 39 | CONFIG_SECTION_SPOT_PARAMS = "Spot Parameters" 40 | CONFIG_SECTION_ECLIPSE_TIMINGS = "Eclipse Timings" 41 | CONFIG_SECTION_CURVE_COUNTS = "Curve Counts" 42 | CONFIG_SECTION_LIGHT_CURVE_STUB = "Light Curve " 43 | CONFIG_SECTION_VELOCITY_CURVE_STUB = "Velocity Curve" 44 | CONFIG_SECTION_STAR1_SPOTS = "Star 1 Spot " 45 | CONFIG_SECTION_STAR2_SPOTS = "Star 2 Spot " 46 | 47 | # dicts 48 | BANDPASS_ID_DICT = { 49 | "Stromgren u": "1", 50 | "Stromgren v": "2", 51 | "Stromgren b": "3", 52 | "Stromgren y": "4", 53 | "Johnson U": "5", 54 | "Johnson B": "6", 55 | "Johnson V": "7", 56 | "Johnson R": "8", 57 | "Johnson I": "9", 58 | "Johnson J": "10", 59 | "Johnson K": "11", 60 | "Johnson L": "12", 61 | "Johnson M": "13", 62 | "Johnson N": "14", 63 | "Cousins Rc": "15", 64 | "Cousins Ic": "16", 65 | "Bessel UX": "17", 66 | "Bessel BX": "18", 67 | "Bessel B": "19", 68 | "Bessel V": "20", 69 | "Bessel R": "21", 70 | "Bessel I": "22", 71 | "Tycho Bt": "23", 72 | "Tycho Vt": "24", 73 | "Hipparchos Hp": "25", 74 | "KEPLER": "26", 75 | "COROT SIS": "27", 76 | "COROT EXO": "28", 77 | "Geneva U": "29", 78 | "Geneva B": "30", 79 | "Geneva B1": "31", 80 | "Geneva B2": "32", 81 | "Geneva V": "33", 82 | "Geneva V1": "34", 83 | "Geneva G": "35", 84 | "Vilnius U": "36", 85 | "Vilnius P": "37", 86 | "Vilnius X": "38", 87 | "Vilnius Y": "39", 88 | "Vilnius Z": "40", 89 | "Vilnius V": "41", 90 | "Vilnius S": "42", 91 | "Milone iz": "43", 92 | "Milone iJ": "44", 93 | "Milone iH": "45", 94 | "Milone iK": "46", 95 | "YMS94 iz": "47", 96 | "YMS94 iJ": "48", 97 | "YMS94 iH": "49", 98 | "YMS94 iK": "50", 99 | "YMS94 iL": "51", 100 | "YMS94 iL'": "52", 101 | "YMS94 iM": "53", 102 | "YMS94 in": "54", 103 | "YMS94 iN": "55", 104 | "Sloan DSS u'": "56", 105 | "Sloan DSS g'": "57", 106 | "Sloan DSS r'": "58", 107 | "Sloan DSS i'": "59", 108 | "Sloan DSS z'": "60", 109 | "HST STIS Ly alpha": "61", 110 | "HST STIS Fclear": "62", 111 | "HST STIS Fsrf2": "63", 112 | "HST STIS Fqtz": "64", 113 | "HST STIS C III": "65", 114 | "HST STIS Mg II": "66", 115 | "HST STIS Nclear": "67", 116 | "HST STIS Nsrf2": "68", 117 | "HST STIS Nqtz": "69", 118 | "HST STIS cn182": "70", 119 | "HST STIS cn270": "71", 120 | "HST STIS Oclear": "72", 121 | "HST STIS Oclear-lp": "73", 122 | "HST STIS [O II]": "74", 123 | "HST STIS [O III]": "75", 124 | "2MASS J": "76", 125 | "2MASS H": "77", 126 | "2MASS Ks": "78", 127 | "SWASP": "79", 128 | "MOST": "80", 129 | "Gaia G (2006)": "81", 130 | "Gaia G (2010)": "82", 131 | "Gaia Gbp": "83", 132 | "Gaia Grp": "84", 133 | "Gaia Grvs": "85", 134 | "Milone 230": "86", 135 | "Milone 250": "87", 136 | "Milone 270": "88", 137 | "Milone 290": "89", 138 | "Milone 310": "90", 139 | "Milone 330": "91", 140 | "Ca II triplet": "92", 141 | "WIRE V+R": "93", 142 | "Lunar Ultraviolet Telescope": "94", 143 | "TESS": "95" 144 | } 145 | ID_BANDPASS_DICT = { 146 | value: key for key, value in list(BANDPASS_ID_DICT.items()) # reverse of the above 147 | } 148 | KEEPS_NAME_ID_DICT = { 149 | "Spot 1 Latitude": 1.0, 150 | "Spot 1 Longitude": 2.0, 151 | "Spot 1 Ang. Rad.": 3.0, 152 | "Spot 1 Temp. Factor": 4.0, 153 | 154 | "Spot 2 Latitude": 5.0, 155 | "Spot 2 Longitude": 6.0, 156 | "Spot 2 Ang. Rad.": 7.0, 157 | "Spot 2 Temp. Factor": 8.0, 158 | 159 | "a": 9.0, 160 | "e": 10.0, 161 | "Omega": 11.0, 162 | "F1": 12.0, 163 | "F2": 13.0, 164 | "Phase Shift": 14.0, 165 | "V Gamma": 15.0, 166 | "i": 16.0, 167 | "g1": 17.0, 168 | "g2": 18.0, 169 | "T1": 19.0, 170 | "T2": 20.0, 171 | "Alb1": 21.0, 172 | "Alb2": 22.0, 173 | "Pot1": 23.0, 174 | "Pot2": 24.0, 175 | "q (M2/M1)": 25.0, 176 | "Epoch": 26.0, 177 | "Period": 27.0, 178 | "dP/dt": 28.0, 179 | "d(Omega)/dt": 29.0, 180 | "a (3B)": 30.0, 181 | "Period (3B)": 31.0, 182 | "i (3B)": 32.0, 183 | "e (3B)": 33.0, 184 | "Omega (3B)": 34., 185 | "Epoch (3B)": 35.0, 186 | "Log(d)": 41.0, 187 | "Desig. Ext.": 42.0, 188 | 189 | "Spot 1 Tstart": 43.0, 190 | "Spot 1 Tmax1": 44.0, 191 | "Spot 1 Tmax2": 45.0, 192 | "Spot 1 Tend": 46.0, 193 | 194 | "Spot 2 Tstart": 47.0, 195 | "Spot 2 Tmax1": 48.0, 196 | "Spot 2 Tmax2": 49.0, 197 | "Spot 2 Tend": 50.0, 198 | 199 | "L1": 56.0, 200 | "L2": 57.0, 201 | "X1": 58.0, 202 | "X2": 59.0, 203 | "L3": 60.0 204 | } 205 | KEEPS_ID_NAME_DICT = { 206 | value: key for key, value in list(KEEPS_NAME_ID_DICT.items()) 207 | } 208 | 209 | ID_LATEX_DICT = { 210 | "1": "$Co-Latitude_{Spot1}$ $(^{\circ})$", 211 | "2": "$Longitude_{Spot1}$ $(^{\circ})$", 212 | "3": "$Radius_{Spot1}$ $(^{\circ})$", 213 | "4": "$Temperature~Factor_{Spot1}$", 214 | "5": "$Co-Latitude_{Spot2}$ $(^{\circ})$", 215 | "6": "$Longitude_{Spot2}$ $(^{\circ})$", 216 | "7": "$Radius_{Spot2}$ $(^{\circ})$", 217 | "8": "$Temperature~Factor_{Spot2}$", 218 | "9": "$a$~({\mbox{$R_{\odot}$}})", 219 | "10": "$e$", 220 | "11": "$\omega~(^{\circ})$", 221 | "12": "$F_{1}$", 222 | "13": "$F_{2}$", 223 | "14": "$Phase~Shift$", 224 | "15": "$V_{\gamma}$", 225 | "16": "$i~(^{\circ})$", 226 | "17": "$g_{1}$", 227 | "18": "$g_{2}$", 228 | "19": "$T_{1}(K)$", 229 | "20": "$T_{2}(K)$", 230 | "21": "$A_{{1}}$", 231 | "22": "$A_{{2}}$", 232 | "23": "$\Omega_{1}$", 233 | "24": "$\Omega_{2}$", 234 | "25": "$q~(=M{_2}/M{_1})$", 235 | "26": "$HJD_{Min1}$", 236 | "27": "$Period$", 237 | "28": "$dP/dt$", 238 | "29": "$d\omega/dt$", 239 | "30": "$a$ ({\mbox{$R_{\odot}$}}) (3B)$", 240 | "31": "$P~(3B)$", 241 | "32": "$i~(3B)~(^{\circ})$", 242 | "33": "$e~(3B)$", 243 | "34": "$\omega~(3B)$", 244 | "35": "$Epoch~(3B)$", 245 | "41": "$log(d)$", 246 | "42": "$Designated~Extinction$", 247 | "43": "nan", 248 | "44": "nan", 249 | "45": "nan", 250 | "46": "nan", 251 | "47": "nan", 252 | "48": "nan", 253 | "49": "nan", 254 | "50": "nan", 255 | "56": "$L_{{1}}$/$(L_{{1}}+L_{{2}})_{{{band}}}$", 256 | "57": "nan", 257 | "58": "$x{{_1}}_{{{band}}}$", 258 | "59": "$x{{_2}}_{{{band}}}$", 259 | "60": "$L_{{3}}$/$(L_{{1}}+L_{{2}}+L_{{3}})_{{{band}}}$" 260 | } 261 | 262 | JDPHS_DICT = { 263 | "Time": 1, 264 | "Phase": 2 265 | } 266 | MAGLITE_DICT = { 267 | "Flux": 0, 268 | "Magnitude": 1 269 | } 270 | MODE_DICT = { 271 | "Mode -1": -1, 272 | "Mode 0": 0, 273 | "Mode 1": 1, 274 | "Mode 2": 2, 275 | "Mode 3": 3, 276 | "Mode 4": 4, 277 | "Mode 5": 5, 278 | "Mode 6": 6 279 | } 280 | ATM_DICT = { 281 | "Stellar Atmosphere": 1, 282 | "Blackbody": 0 283 | } 284 | LIMB_DICT = { 285 | "Linear Cosine": 1, 286 | "Logarithmic": 2, 287 | "Square Root": 3 288 | } 289 | DERIV_DICT = { 290 | "Symmetrical": 1, 291 | "Asymmetrical": 0 292 | } 293 | NOMAX_DICT = { 294 | "Triangular": 1, 295 | "Trapezoidal": 0 296 | } 297 | NOISE_DICT = { 298 | "No Scaling": 0, 299 | "Square Root": 1, 300 | "Linear": 2 301 | } 302 | -------------------------------------------------------------------------------- /src/helpers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/src/helpers/__init__.py -------------------------------------------------------------------------------- /src/helpers/matplotlib_embedder.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtCore 2 | from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 3 | from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar 4 | from matplotlib.figure import Figure 5 | from matplotlib.gridspec import GridSpec 6 | import numpy 7 | import pickle 8 | from src import constants 9 | 10 | 11 | delimiter = constants.EXPORT_DELIMITER 12 | 13 | 14 | class MatplotlibWidget: 15 | def __init__(self, widget, rows, cols, h_ratios=None, w_ratios=None, 16 | poppable=True, exportable=True, grid_allowed=True): 17 | 18 | if h_ratios is None: 19 | h_ratios = numpy.ones(rows) 20 | 21 | if w_ratios is None: 22 | w_ratios = numpy.ones(cols) 23 | 24 | # properties 25 | self.rows = rows 26 | self.cols = cols 27 | self.widget = widget 28 | 29 | self.axes = [] 30 | self.titles = [] 31 | self.labels = [] 32 | 33 | self.figure = Figure() 34 | self.gridspec = GridSpec(rows, cols, figure=self.figure, 35 | height_ratios=list(h_ratios), width_ratios=list(w_ratios)) 36 | self.canvas = FigureCanvas(self.figure) 37 | self.toolbar = NavigationToolbar(self.canvas, widget) 38 | 39 | # custom ui elements 40 | self.pop_button = QtWidgets.QPushButton(widget) 41 | self.pop_button.setText("Pop Plot Window") 42 | 43 | self.export_button = QtWidgets.QPushButton(widget) 44 | self.export_button.setText("Export Currently Plotted Data") 45 | 46 | self.grid_checkbox = QtWidgets.QCheckBox(widget) 47 | self.grid_checkbox.setText("Enable Grid") 48 | self.grid_checkbox.setChecked(False) 49 | 50 | self.popped_windows = [] 51 | 52 | if not poppable: 53 | self.pop_button.hide() 54 | 55 | if not exportable: 56 | self.export_button.hide() 57 | 58 | if not grid_allowed: 59 | self.grid_checkbox.hide() 60 | 61 | # set layouts 62 | self.layout_horizontal = QtWidgets.QHBoxLayout() 63 | self.layout_horizontal.addWidget(self.pop_button) 64 | self.layout_horizontal.addWidget(self.export_button) 65 | self.layout_horizontal.addWidget(self.grid_checkbox) 66 | 67 | self.layout_vertical = QtWidgets.QVBoxLayout(widget) 68 | self.layout_vertical.addWidget(self.canvas) 69 | self.layout_vertical.addWidget(self.toolbar) 70 | self.layout_vertical.addLayout(self.layout_horizontal) 71 | 72 | # connect signals 73 | self.connect_signals() 74 | 75 | def connect_signals(self): 76 | self.pop_button.clicked.connect(self.pop) 77 | self.export_button.clicked.connect(self.export) 78 | self.grid_checkbox.toggled.connect(self.toggle_grid) 79 | 80 | def clean_popped_windows(self): 81 | for window in self.popped_windows: 82 | if not window.isVisible(): 83 | a = self.popped_windows.pop(self.popped_windows.index(window)) 84 | a.setParent(None) 85 | a.deleteLater() 86 | del a 87 | 88 | def close_popped_windows(self): 89 | self.clean_popped_windows() 90 | for window in self.popped_windows: 91 | window.close() 92 | self.popped_windows = [] 93 | 94 | def pop(self): 95 | self.clean_popped_windows() 96 | window = PopWidget(self) 97 | self.popped_windows.append(window) 98 | window.show() 99 | 100 | def export(self): 101 | output = "# Data exported from a matplotlib figure\n\n" 102 | 103 | for idx, ax in enumerate(self.axes): 104 | output = output + "# Axis {0}\n".format(str(idx + 1)) 105 | for line in ax.get_lines(): 106 | xdata = line.get_xdata() 107 | ydata = line.get_ydata() 108 | 109 | try: 110 | float(xdata[0]) 111 | float(ydata[0]) 112 | 113 | except: 114 | # if we cant cast an array element into a float, most likely we dont need it 115 | continue 116 | 117 | for x, y in zip(xdata, ydata): # "{:0.5f}" 118 | output = output + "{0:0.5f}{2}{1:0.10f}\n".format(x, y, delimiter) 119 | 120 | output = output + "\n" 121 | 122 | dialog = QtWidgets.QFileDialog() 123 | dialog.setDefaultSuffix(".dat") 124 | dialog.setAcceptMode(1) 125 | return_code = dialog.exec_() 126 | if return_code != 0: 127 | path = str((dialog.selectedFiles())[0]) 128 | with open(path, "w") as destination: 129 | destination.write(output) 130 | 131 | msg = QtWidgets.QMessageBox() 132 | msg.setText("File saved:") 133 | msg.setInformativeText(path) 134 | msg.setIcon(QtWidgets.QMessageBox.Information) 135 | msg.exec_() 136 | 137 | def toggle_grid(self): 138 | 139 | for ax in self.axes: 140 | ax.grid(visible=self.grid_checkbox.isChecked()) 141 | 142 | self.redraw() 143 | 144 | def create_axis(self, row_idx, col_idx, name="", labels=("", ""), *subplot_args, **subplot_kwargs): 145 | 146 | # setup axis 147 | if isinstance(row_idx, tuple): 148 | row_idx = slice(row_idx[0], row_idx[1]) 149 | if isinstance(col_idx, tuple): 150 | col_idx = slice(col_idx[0], col_idx[1]) 151 | self.axes.append(self.figure.add_subplot(self.gridspec[row_idx, col_idx], *subplot_args, **subplot_kwargs)) 152 | 153 | # setup title 154 | self.titles.append(name) 155 | self.axes[-1].set_title(name) 156 | 157 | # setup labels 158 | self.labels.append(labels) 159 | self.axes[-1].set_xlabel(labels[0]) 160 | self.axes[-1].set_ylabel(labels[1]) 161 | 162 | self.redraw() 163 | 164 | def set_axis_title(self, title, index=0): 165 | self.titles[index] = title 166 | self.axes[index].set_title(title) 167 | self.redraw() 168 | 169 | def set_labels(self, x_label, y_label, index=0): 170 | self.labels[index] = (x_label, y_label) 171 | self.axes[index].set_xlabel(x_label) 172 | self.axes[index].set_ylabel(y_label) 173 | self.redraw() 174 | 175 | def plot(self, x, y, index=0, clear=True, update_toolbar=True, *plot_args, **plot_kwargs): 176 | 177 | # clear plot if requested 178 | if clear: 179 | self.clear_axis(index) 180 | 181 | # plot the data 182 | self.axes[index].plot(x, y, *plot_args, **plot_kwargs) 183 | 184 | # reorient axis if requested 185 | if update_toolbar: 186 | self.toolbar.update() 187 | 188 | # redraw title 189 | self.axes[index].set_title(self.titles[index]) 190 | 191 | # redraw labels 192 | self.axes[index].set_xlabel(self.labels[index][0]) 193 | self.axes[index].set_ylabel(self.labels[index][1]) 194 | self.axes[index].ticklabel_format(useOffset=False) 195 | 196 | # finally, draw the canvas 197 | self.canvas.draw() 198 | 199 | def get_plot_data(self, index=0): 200 | x = self.axes[index].lines[0].get_xdata() 201 | y = self.axes[index].lines[0].get_ydata() 202 | return x, y 203 | 204 | def clear_all(self): 205 | for axis in self.axes: 206 | axis.clear() 207 | self.redraw() 208 | 209 | def clear_axis(self, index): 210 | self.axes[index].clear() 211 | 212 | def redraw(self): 213 | self.canvas.draw() 214 | 215 | def __getitem__(self, item): 216 | return self.axes[item] 217 | 218 | 219 | class PopWidget(QtWidgets.QWidget): 220 | def __init__(self, parent): 221 | super(PopWidget, self).__init__() 222 | self.parent_widget = parent 223 | 224 | # create a simple container ui 225 | self.setObjectName("PopPlotDialog") 226 | self.setWindowTitle("PyWD2015") 227 | self.resize(900, 500) 228 | self.setMinimumSize(300, 300) 229 | h_layout = QtWidgets.QHBoxLayout(self) 230 | self.plot_widget = QtWidgets.QWidget(self) 231 | 232 | # create a new canvas from the old figure 233 | # we'll just dump and load the parent figure to create a new figure instance 234 | # otherwise parent widget's canvas will be broken 235 | self.canvas = FigureCanvas(figure=pickle.loads(pickle.dumps(self.parent_widget.figure))) 236 | self.toolbar = NavigationToolbar(self.canvas, self.plot_widget) 237 | 238 | # fill layouts with created widgets 239 | h_layout.addWidget(self.plot_widget) 240 | v_layout = QtWidgets.QVBoxLayout(self.plot_widget) 241 | v_layout.addWidget(self.canvas) 242 | v_layout.addWidget(self.toolbar) 243 | 244 | QtCore.QMetaObject.connectSlotsByName(self) 245 | 246 | def closeEvent(self, *args, **kwargs): 247 | for ax in self.canvas.figure.get_axes(): 248 | ax.clear() 249 | del self.canvas 250 | del self.toolbar 251 | self.parent_widget.clean_popped_windows() 252 | -------------------------------------------------------------------------------- /src/helpers/messenger.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from src import constants 3 | 4 | 5 | class Messenger: 6 | def __init__(self, icon_type, msg): 7 | self.msg_box = QtWidgets.QMessageBox() 8 | self.msg_box.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 9 | self.msg_box.setText(msg) 10 | self.msg_box.setWindowTitle("PyWD2015") 11 | if icon_type == "info": 12 | self.msg_box.setIcon(QtWidgets.QMessageBox.Information) 13 | elif icon_type == "warning": 14 | self.msg_box.setIcon(QtWidgets.QMessageBox.Warning) 15 | elif icon_type == "question": 16 | self.msg_box.setIcon(QtWidgets.QMessageBox.Question) 17 | elif icon_type == "error": 18 | self.msg_box.setIcon(QtWidgets.QMessageBox.Critical) 19 | 20 | def show(self): 21 | return self.msg_box.exec_() 22 | 23 | def set_info(self, msg): 24 | self.msg_box.setInformativeText(msg) 25 | -------------------------------------------------------------------------------- /src/helpers/wd_utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/src/helpers/wd_utils/__init__.py -------------------------------------------------------------------------------- /src/helpers/wd_utils/wd_constants.py: -------------------------------------------------------------------------------- 1 | # a dictionary mapping names to ID's of DC keeps 2 | DC_KEEPS_NAME_ID_DICT = { 3 | "spot_a_lat": 1.0, 4 | "spot_a_long": 2.0, 5 | "spot_a_rad": 3.0, 6 | "spot_a_tempf": 4.0, 7 | 8 | "spot_b_lat": 5.0, 9 | "spot_b_long": 6.0, 10 | "spot_b_rad": 7.0, 11 | "spot_b_tempf": 8.0, 12 | 13 | "a": 9.0, 14 | "e": 10.0, 15 | "perr": 11.0, 16 | "f1": 12.0, 17 | "f2": 13.0, 18 | "pshift": 14.0, 19 | "vga": 15.0, 20 | "xincl": 16.0, 21 | "g1": 17.0, 22 | "g2": 18.0, 23 | "tavc": 19.0, 24 | "tavh": 20.0, 25 | "alb1": 21.0, 26 | "alb2": 22.0, 27 | "phsv": 23.0, 28 | "pcsv": 24.0, 29 | "rm": 25.0, 30 | "hjd0": 26.0, 31 | "pzero": 27.0, 32 | "dpdt": 28.0, 33 | "dperdt": 29.0, 34 | "a3b": 30.0, 35 | "p3b": 31.0, 36 | "xincl3b": 32.0, 37 | "e3b": 33.0, 38 | "perr3b": 34., 39 | "t03b": 35.0, 40 | "dpclog": 41.0, 41 | "desextinc": 42.0, 42 | 43 | "spot_a_tstart": 43.0, 44 | "spot_a_tmax1": 44.0, 45 | "spot_a_tmax2": 45.0, 46 | "spot_a_tend": 46.0, 47 | 48 | "spot_b_tstart": 47.0, 49 | "spot_b_tmax1": 48.0, 50 | "spot_b_tmax2": 49.0, 51 | "spot_b_tend": 50.0, 52 | 53 | "hla": 56.0, 54 | "cla": 57.0, 55 | "x1a": 58.0, 56 | "x2a": 59.0, 57 | "el3a": 60.0 58 | } 59 | 60 | # reverse of the dictionary above 61 | DC_KEEPS_ID_NAME_DICT = {value: key for key, value in list(DC_KEEPS_NAME_ID_DICT.items())} 62 | -------------------------------------------------------------------------------- /src/interfaces/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Varnani/pywd2015-qt5/b6d6202878e16ed3f0a84da045f4168bd717aec2/src/interfaces/__init__.py -------------------------------------------------------------------------------- /src/interfaces/configurespots_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import configurespots_widget 3 | from src import constants 4 | from configparser import ConfigParser 5 | from src.helpers import methods, messenger 6 | 7 | 8 | class Widget(QtWidgets.QWidget, configurespots_widget.Ui_SpotConfigureWidget): 9 | def __init__(self, parent): 10 | super(Widget, self).__init__() 11 | self.setupUi(self) 12 | 13 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 14 | 15 | self.main_window = parent 16 | 17 | self.star1_treewidget = SpotTreeWidget(self.star1_groupbox, self, 1) 18 | self.star2_treewidget = SpotTreeWidget(self.star2_groupbox, self, 2) 19 | 20 | self.a_btn_group = QtWidgets.QButtonGroup() 21 | self.b_btn_group = QtWidgets.QButtonGroup() 22 | 23 | self.connect_signals() 24 | 25 | def connect_signals(self): 26 | self.whatsthis_btn.clicked.connect(QtWidgets.QWhatsThis.enterWhatsThisMode) 27 | self.clear_a_b_button.clicked.connect(self.clear_a_b) 28 | self.spotconfigsave_btn.clicked.connect(self.save_spots) 29 | self.spotconfigload_btn.clicked.connect(self.load_spots) 30 | 31 | def clear_a_b(self): 32 | self.a_btn_group.setExclusive(False) 33 | self.b_btn_group.setExclusive(False) 34 | 35 | for btn in self.a_btn_group.buttons(): 36 | btn.setChecked(False) 37 | 38 | for btn in self.b_btn_group.buttons(): 39 | btn.setChecked(False) 40 | 41 | self.a_btn_group.setExclusive(True) 42 | self.b_btn_group.setExclusive(True) 43 | 44 | def write_into_parser(self, parser): 45 | parser.add_section(constants.CONFIG_SECTION_SPOT_PARAMS) 46 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, "fspot1", str(self.fspot1_ipt.value())) 47 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, "fspot2", str(self.fspot2_ipt.value())) 48 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, "ifsvm1", str(self.ifsmv1_chk.isChecked())) 49 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, "ifsvm2", str(self.ifsmv2_chk.isChecked())) 50 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, "kspev", str(self.kspev_groupbox.isChecked())) 51 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, "nomax", str(self.nomax_combobox.currentIndex())) 52 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, "kspot", str(self.kspot_chk.isChecked())) 53 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, constants.CONFIG_SECTION_STAR1_SPOTS + "count", 54 | str(self.star1_treewidget.tree_widget.invisibleRootItem().childCount())) 55 | parser.set(constants.CONFIG_SECTION_SPOT_PARAMS, constants.CONFIG_SECTION_STAR2_SPOTS + "count", 56 | str(self.star2_treewidget.tree_widget.invisibleRootItem().childCount())) 57 | 58 | parser = self.star1_treewidget.write_into_parser(parser) 59 | parser = self.star2_treewidget.write_into_parser(parser) 60 | 61 | return parser 62 | 63 | def read_from_parser(self, parser): 64 | self.fspot1_ipt.setValue(parser.getfloat(constants.CONFIG_SECTION_SPOT_PARAMS, "fspot1")) 65 | self.fspot2_ipt.setValue(parser.getfloat(constants.CONFIG_SECTION_SPOT_PARAMS, "fspot2")) 66 | self.ifsmv1_chk.setChecked(parser.getboolean(constants.CONFIG_SECTION_SPOT_PARAMS, "ifsvm1")) 67 | self.ifsmv2_chk.setChecked(parser.getboolean(constants.CONFIG_SECTION_SPOT_PARAMS, "ifsvm2")) 68 | self.kspev_groupbox.setChecked(parser.getboolean(constants.CONFIG_SECTION_SPOT_PARAMS, "kspev",)) 69 | self.nomax_combobox.setCurrentIndex(parser.getint(constants.CONFIG_SECTION_SPOT_PARAMS, "nomax",)) 70 | self.kspot_chk.setChecked(parser.getboolean(constants.CONFIG_SECTION_SPOT_PARAMS, "kspot",)) 71 | 72 | self.star1_treewidget.read_from_parser(parser) 73 | self.star2_treewidget.read_from_parser(parser) 74 | 75 | def save_spots(self): 76 | save_path = methods.save_file(self, suffix=".pywdspot", name_filter="PyWD2015 spot file (*.pywdspot)") 77 | if save_path is not None: 78 | parser = self.write_into_parser(ConfigParser()) 79 | 80 | with open(save_path, "w") as destination: 81 | parser.write(destination) 82 | 83 | msg = messenger.Messenger("info", "Save completed:") 84 | msg.set_info(save_path) 85 | msg.show() 86 | 87 | def load_spots(self): 88 | load_path = methods.load_file(self, suffix=".pywdspot", name_filter="PyWD2015 spot file (*.pywdspot);;" 89 | "PyWD2015 project file (*.pywdproject)") 90 | if load_path is not None: 91 | parser = ConfigParser() 92 | with open(load_path, "r") as source: 93 | parser.read_file(source) 94 | 95 | self.read_from_parser(parser) 96 | 97 | msg = messenger.Messenger("info", "Load completed:") 98 | msg.set_info(load_path) 99 | msg.show() 100 | 101 | def get_all_spots(self, get_ab=False): 102 | def _from_item_to_list(item, parent, ab=False): 103 | value_list = [parent.itemWidget(item, 2).value(), parent.itemWidget(item, 3).value(), 104 | parent.itemWidget(item, 4).value(), parent.itemWidget(item, 5).value(), 105 | parent.itemWidget(item, 6).value(), parent.itemWidget(item, 7).value(), 106 | parent.itemWidget(item, 8).value(), parent.itemWidget(item, 9).value()] 107 | 108 | if ab: 109 | value_list.append(parent.itemWidget(item, 0).isChecked()) 110 | value_list.append(parent.itemWidget(item, 1).isChecked()) 111 | 112 | return value_list 113 | 114 | s1_spot_items = self.star1_treewidget.get_all_items() 115 | s2_spot_items = self.star2_treewidget.get_all_items() 116 | 117 | s1_spots = [_from_item_to_list(spot_item, self.star1_treewidget.tree_widget, ab=get_ab) 118 | for spot_item in s1_spot_items] 119 | s2_spots = [_from_item_to_list(spot_item, self.star2_treewidget.tree_widget, ab=get_ab) 120 | for spot_item in s2_spot_items] 121 | 122 | return s1_spots, s2_spots 123 | 124 | 125 | class SpotTreeWidget: 126 | def __init__(self, groupbox, parent, star): 127 | 128 | self.star = star 129 | self.groupbox = groupbox 130 | self.v_layout = QtWidgets.QVBoxLayout(self.groupbox) 131 | self.tree_widget = QtWidgets.QTreeWidget() 132 | self.v_layout.addWidget(self.tree_widget) 133 | self.h_layout = QtWidgets.QHBoxLayout() 134 | self.add_spot_button = QtWidgets.QPushButton() 135 | self.add_spot_button.setText("Add Spot") 136 | self.remove_spot_button = QtWidgets.QPushButton() 137 | self.remove_spot_button.setText("Remove Selected Spot") 138 | self.h_layout.addWidget(self.add_spot_button) 139 | self.h_layout.addWidget(self.remove_spot_button) 140 | self.v_layout.addLayout(self.h_layout) 141 | 142 | self.parent_widget = parent 143 | 144 | columns = ["A", "B", "LAT", "LON", "RADSP", "TEMSP", "Tstart", "Tmax1", "Tmax2", "Tend"] 145 | 146 | header_item = QtWidgets.QTreeWidgetItem() 147 | for index, column in enumerate(columns): 148 | header_item.setText(index, column) 149 | 150 | self.tree_widget.setHeaderItem(header_item) 151 | self.header_item_count = len(columns) 152 | 153 | self.tree_widget.header().setSectionResizeMode(1) 154 | self.tree_widget.header().setSectionsMovable(False) 155 | 156 | self.connect_signals() 157 | 158 | def connect_signals(self): 159 | self.add_spot_button.clicked.connect(self.insert_row) 160 | self.remove_spot_button.clicked.connect(self.remove_spot_row) 161 | 162 | def remove_spot_row(self): 163 | item = self.selected_item() 164 | self.tree_widget.headerItem().removeChild(item) 165 | 166 | def selected_item(self): 167 | selecteditem = self.tree_widget.selectedItems() 168 | if len(selecteditem) > 0: 169 | return selecteditem[0] 170 | else: 171 | return None 172 | 173 | def insert_row(self, ): 174 | item = QtWidgets.QTreeWidgetItem(self.tree_widget) 175 | 176 | a_radio_button = QtWidgets.QRadioButton() 177 | a_radio_button.setText("A") 178 | b_radio_button = QtWidgets.QRadioButton() 179 | b_radio_button.setText("B") 180 | 181 | self.parent_widget.a_btn_group.addButton(a_radio_button) 182 | self.parent_widget.b_btn_group.addButton(b_radio_button) 183 | 184 | self.tree_widget.setItemWidget(item, 0, a_radio_button) 185 | self.tree_widget.setItemWidget(item, 1, b_radio_button) 186 | 187 | i = 2 188 | while i < self.header_item_count: 189 | spinbox = QtWidgets.QDoubleSpinBox(self.tree_widget) 190 | spinbox.setButtonSymbols(2) 191 | spinbox.setDecimals(8) 192 | spinbox.setMaximum(9999999) 193 | spinbox.setMinimum(0) 194 | self.tree_widget.setItemWidget(item, i, spinbox) 195 | i = i + 1 196 | 197 | return item 198 | 199 | def get_section(self): 200 | 201 | section = "" 202 | 203 | if self.star == 1: 204 | section = constants.CONFIG_SECTION_STAR1_SPOTS 205 | 206 | if self.star == 2: 207 | section = constants.CONFIG_SECTION_STAR2_SPOTS 208 | 209 | return section 210 | 211 | def get_all_items(self): 212 | count = self.tree_widget.invisibleRootItem().childCount() 213 | children = [] 214 | i = 0 215 | while i < count: 216 | children.append(self.tree_widget.invisibleRootItem().child(i)) 217 | i = i + 1 218 | 219 | return children 220 | 221 | def write_into_parser(self, parser): 222 | section = self.get_section() 223 | 224 | for i, child in enumerate(self.get_all_items()): 225 | sct = section + str(i + 1) 226 | parser.add_section(sct) 227 | parser.set(sct, "a", str(self.tree_widget.itemWidget(child, 0).isChecked())) 228 | parser.set(sct, "b", str(self.tree_widget.itemWidget(child, 1).isChecked())) 229 | parser.set(sct, "lat", str(self.tree_widget.itemWidget(child, 2).value())) 230 | parser.set(sct, "lon", str(self.tree_widget.itemWidget(child, 3).value())) 231 | parser.set(sct, "radsp", str(self.tree_widget.itemWidget(child, 4).value())) 232 | parser.set(sct, "temsp", str(self.tree_widget.itemWidget(child, 5).value())) 233 | parser.set(sct, "tstart", str(self.tree_widget.itemWidget(child, 6).value())) 234 | parser.set(sct, "tmax1", str(self.tree_widget.itemWidget(child, 7).value())) 235 | parser.set(sct, "tmax2", str(self.tree_widget.itemWidget(child, 8).value())) 236 | parser.set(sct, "tend", str(self.tree_widget.itemWidget(child, 9).value())) 237 | 238 | return parser 239 | 240 | def read_from_parser(self, parser): 241 | self.tree_widget.clear() 242 | 243 | i = 1 244 | while i <= parser.getint(constants.CONFIG_SECTION_SPOT_PARAMS, self.get_section() + "count"): 245 | section = self.get_section() + str(i) 246 | item = self.insert_row() 247 | self.tree_widget.itemWidget(item, 0).setChecked(parser.getboolean(section, "a")) 248 | self.tree_widget.itemWidget(item, 1).setChecked(parser.getboolean(section, "b")) 249 | self.tree_widget.itemWidget(item, 2).setValue(parser.getfloat(section, "lat")) 250 | self.tree_widget.itemWidget(item, 3).setValue(parser.getfloat(section, "lon")) 251 | self.tree_widget.itemWidget(item, 4).setValue(parser.getfloat(section, "radsp")) 252 | self.tree_widget.itemWidget(item, 5).setValue(parser.getfloat(section, "temsp")) 253 | self.tree_widget.itemWidget(item, 6).setValue(parser.getfloat(section, "tstart")) 254 | self.tree_widget.itemWidget(item, 7).setValue(parser.getfloat(section, "tmax1")) 255 | self.tree_widget.itemWidget(item, 8).setValue(parser.getfloat(section, "tmax2")) 256 | self.tree_widget.itemWidget(item, 9).setValue(parser.getfloat(section, "tend")) 257 | 258 | i = i + 1 259 | -------------------------------------------------------------------------------- /src/interfaces/conjunction_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import conjunction_widget 3 | from src import constants 4 | from src.helpers.wd_utils import wd_io 5 | from src.helpers import methods 6 | from src.helpers import messenger 7 | import numpy 8 | 9 | 10 | delimiter = constants.EXPORT_DELIMITER 11 | 12 | 13 | class Widget(QtWidgets.QWidget, conjunction_widget.Ui_conjunctionwidget): 14 | def __init__(self, parent): 15 | super(Widget, self).__init__() 16 | self.setupUi(self) 17 | 18 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 19 | 20 | self.main_window = parent 21 | 22 | self.data_treewidget.setFont(parent.monoFont) 23 | self.data_treewidget.header().setSectionResizeMode(3) 24 | 25 | self.connect_signals() 26 | 27 | def connect_signals(self): 28 | self.compute_btn.clicked.connect(self.compute_conjunction) 29 | self.export_btn.clicked.connect(self.export_data) 30 | 31 | def export_data(self): 32 | root = self.data_treewidget.invisibleRootItem() 33 | if root.childCount() == 0: 34 | return 1 35 | 36 | filepath = methods.save_file(self, suffix="txt") 37 | if filepath is not None: 38 | lenght = None 39 | output = "" 40 | 41 | if self.ut_groupbox.isChecked(): 42 | lenght = 3 43 | if self.dt_groupbox.isChecked(): 44 | output = "# JD" + delimiter + "MinType" + delimiter + "Time\n" 45 | else: 46 | output = "# HJD" + delimiter + "MinType" + delimiter + "Time\n" 47 | 48 | else: 49 | lenght = 2 50 | output = "# HJD" + delimiter + "MinType\n" 51 | 52 | root = self.data_treewidget.invisibleRootItem() 53 | i = 0 54 | while i < root.childCount(): 55 | idx = 0 56 | while idx < lenght: 57 | output = output + root.child(i).text(idx) + delimiter 58 | idx = idx + 1 59 | 60 | output = output + "\n" 61 | i = i + 1 62 | 63 | with open(filepath, "w") as destination: 64 | destination.write(output) 65 | 66 | msg = messenger.Messenger("info", "File saved:") 67 | msg.set_info(filepath) 68 | msg.show() 69 | 70 | def compute_conjunction(self): 71 | self.data_treewidget.clear() 72 | 73 | lc_params = self.main_window.get_lc_params() 74 | 75 | lc_io = wd_io.LCIO(lc_params, 76 | wd_path=self.main_window.lc_path, 77 | lc_binary_name=self.main_window.lc_binary) 78 | 79 | results = lc_io.fill_for_conjunction(self.kstep_spinbox.value()).save().run().read_conjunction() 80 | 81 | i = 0 82 | while i < len(results[0]): 83 | jd = results[0][i] 84 | mn = results[1][i] 85 | 86 | item = QtWidgets.QTreeWidgetItem(self.data_treewidget) 87 | 88 | if self.ut_groupbox.isChecked(): 89 | if self.dt_groupbox.isChecked(): 90 | jd = methods.convert_hjd_to_jd(jd, 91 | self.ra_h_spinbox.value(), 92 | self.ra_m_spinbox.value(), 93 | self.ra_s_spinbox.value(), 94 | self.dec_d_spinbox.value(), 95 | self.dec_m_spinbox.value(), 96 | self.dec_s_spinbox.value()) 97 | 98 | year, month, day, hour, minute, second = methods.convert_jd_to_ut(jd) 99 | item.setText(2, str(day) + "/" + str(month) + "/" + str(year) + " - " + 100 | str(hour) + "/" + str(minute) + "/" + str(numpy.round(second, decimals=3))) 101 | 102 | item.setText(0, str(numpy.round(jd, decimals=5))) 103 | item.setText(1, str(int(mn))) 104 | i = i + 1 105 | 106 | header_item = QtWidgets.QTreeWidgetItem() 107 | if self.ut_groupbox.isChecked() and self.dt_groupbox.isChecked(): 108 | header_item.setText(0, "JD") 109 | else: 110 | header_item.setText(0, "HJD") 111 | header_item.setText(1, "Min") 112 | header_item.setText(2, "D/M/Y - H:M:S") 113 | self.data_treewidget.setHeaderItem(header_item) 114 | -------------------------------------------------------------------------------- /src/interfaces/dimension_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import dimensions_widget 3 | from src.helpers.matplotlib_embedder import MatplotlibWidget 4 | from src import constants 5 | from src.helpers.wd_utils import wd_io 6 | 7 | 8 | class Widget(QtWidgets.QWidget, dimensions_widget.Ui_DimensionWidget): 9 | def __init__(self, parent): 10 | super(Widget, self).__init__() 11 | self.setupUi(self) 12 | 13 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 14 | 15 | self.main_window = parent 16 | 17 | self.s1_chart = MatplotlibWidget(self.s1_plot_widget, 1, 1) 18 | self.s2_chart = MatplotlibWidget(self.s2_plot_widget, 1, 1) 19 | self.s1_chart.create_axis(0, 0, name="Primary Star Dimensions", labels=("", "Fract. Radius")) 20 | self.s2_chart.create_axis(0, 0, name="Secondary Star Dimensions", labels=("", "Fract. Radius")) 21 | 22 | self.s1_pole = [] 23 | self.s1_point = [] 24 | self.s1_side = [] 25 | self.s1_back = [] 26 | 27 | self.s2_pole = [] 28 | self.s2_point = [] 29 | self.s2_side = [] 30 | self.s2_back = [] 31 | 32 | self.x = [] 33 | 34 | self.connect_signals() 35 | 36 | def connect_signals(self): 37 | self.plot_btn.clicked.connect(self.calculate_and_plot) 38 | 39 | self.s1_pole_chk.toggled.connect(self.update_plots) 40 | self.s1_point_chk.toggled.connect(self.update_plots) 41 | self.s1_side_chk.toggled.connect(self.update_plots) 42 | self.s1_back_chk.toggled.connect(self.update_plots) 43 | 44 | self.s2_pole_chk.toggled.connect(self.update_plots) 45 | self.s2_point_chk.toggled.connect(self.update_plots) 46 | self.s2_side_chk.toggled.connect(self.update_plots) 47 | self.s2_back_chk.toggled.connect(self.update_plots) 48 | 49 | def calculate_and_plot(self): 50 | self.calculate_component_radii() 51 | self.update_plots() 52 | 53 | def update_plots(self): 54 | self.s1_chart.clear_all() 55 | self.s2_chart.clear_all() 56 | 57 | if self.s1_pole_chk.isChecked(): 58 | self.s1_chart.plot(self.x, self.s1_pole, clear=False, color=constants.COLOR_BLUE) 59 | if self.s1_point_chk.isChecked(): 60 | self.s1_chart.plot(self.x, self.s1_point, clear=False, color="black") 61 | if self.s1_side_chk.isChecked(): 62 | self.s1_chart.plot(self.x, self.s1_side, clear=False, color=constants.COLOR_RED) 63 | if self.s1_back_chk.isChecked(): 64 | self.s1_chart.plot(self.x, self.s1_back, clear=False, color=constants.COLOR_GREEN) 65 | 66 | if self.s2_pole_chk.isChecked(): 67 | self.s2_chart.plot(self.x, self.s2_pole, clear=False, color=constants.COLOR_BLUE) 68 | if self.s2_point_chk.isChecked(): 69 | self.s2_chart.plot(self.x, self.s2_point, clear=False, color="black") 70 | if self.s2_side_chk.isChecked(): 71 | self.s2_chart.plot(self.x, self.s2_side, clear=False, color=constants.COLOR_RED) 72 | if self.s2_back_chk.isChecked(): 73 | self.s2_chart.plot(self.x, self.s2_back, clear=False, color=constants.COLOR_GREEN) 74 | 75 | def calculate_component_radii(self): 76 | lc_params = self.main_window.get_lc_params() 77 | 78 | lc_io = wd_io.LCIO(lc_params, 79 | wd_path=self.main_window.lc_path, 80 | lc_binary_name=self.main_window.lc_binary) 81 | 82 | results = lc_io.fill_for_component_dimensions().save().run().read_component_dimensions() 83 | 84 | x_index = None 85 | if self.main_window.jd_radiobtn.isChecked(): 86 | x_index = 0 87 | self.s1_chart.set_labels("HJD", "Fract. Radius") 88 | self.s2_chart.set_labels("HJD", "Fract. Radius") 89 | 90 | elif self.main_window.phase_radiobtn.isChecked(): 91 | x_index = 1 92 | self.s1_chart.set_labels("Phase", "Fract. Radius") 93 | self.s2_chart.set_labels("Phase", "Fract. Radius") 94 | 95 | self.x = results[x_index] 96 | 97 | self.s1_pole = results[2] 98 | self.s1_point = results[3] 99 | self.s1_side = results[4] 100 | self.s1_back = results[5] 101 | 102 | self.s2_pole = results[6] 103 | self.s2_point = results[7] 104 | self.s2_side = results[8] 105 | self.s2_back = results[9] 106 | 107 | self.update_plots() 108 | 109 | def clear(self): 110 | self.s1_chart.clear_all() 111 | self.s2_chart.clear_all() 112 | 113 | self.s1_pole = [] 114 | self.s1_point = [] 115 | self.s1_side = [] 116 | self.s1_back = [] 117 | 118 | self.s2_pole = [] 119 | self.s2_point = [] 120 | self.s2_side = [] 121 | self.s2_back = [] 122 | 123 | self.x = [] 124 | -------------------------------------------------------------------------------- /src/interfaces/eclipsetimings_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import eclipsetimings_widget 3 | from src.helpers import methods, messenger 4 | import numpy 5 | from src import constants 6 | 7 | 8 | class Widget(QtWidgets.QWidget, eclipsetimings_widget.Ui_EclipseWidget): 9 | def __init__(self, parent): 10 | super(Widget, self).__init__() 11 | self.setupUi(self) 12 | 13 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 14 | 15 | self.main_window = parent 16 | self.datawidget.setFont(parent.monoFont) 17 | self.datawidget.header().setSectionResizeMode(3) 18 | self.connect_signals() 19 | 20 | def connect_signals(self): 21 | self.load_btn.clicked.connect(self.load_file) 22 | self.clear_btn.clicked.connect(self.clear_timings) 23 | 24 | def load_file(self): 25 | filepath = methods.load_file(self) 26 | if filepath is not None: 27 | self.load_timings(filepath) 28 | 29 | def get_data(self): 30 | data = numpy.loadtxt(self.filepath_label.text(), unpack=True) 31 | 32 | if len(data) == 2: 33 | _ = list(data) 34 | _.append([]) 35 | data = numpy.array(_) 36 | 37 | if self.constant_weight_checkbox.isChecked(): 38 | data[2] = numpy.ones(len(data[1])) 39 | 40 | return data 41 | 42 | def load_timings(self, filepath): 43 | try: 44 | data = numpy.loadtxt(filepath, unpack=True) 45 | if 1 > len(data): 46 | raise IndexError("File has less than 2 columns.") 47 | 48 | except ValueError as e: 49 | msg = messenger.Messenger("error", "A ValueError has occured:") 50 | msg.set_info(e.args[0] + "\nEclipse times are not loaded.") 51 | msg.show() 52 | return False 53 | 54 | except IndexError as e: 55 | msg = messenger.Messenger("error", "An IndexError has occured:") 56 | msg.set_info(e.args[0] + "\nEclipse times are not loaded.") 57 | msg.show() 58 | return False 59 | 60 | self.datawidget.clear() 61 | 62 | for row_idx in range(len(data[0])): 63 | item = QtWidgets.QTreeWidgetItem(self.datawidget) 64 | for col_idx in range(len(data)): 65 | item.setText(col_idx, str(data[col_idx][row_idx])) 66 | 67 | self.filepath_label.setText(filepath) 68 | 69 | def clear_timings(self): 70 | self.datawidget.clear() 71 | self.ksd_box.setValue(1) 72 | self.sigma_ipt.setValue(0.0) 73 | self.iftime_chk.setChecked(False) 74 | self.constant_weight_checkbox.setChecked(False) 75 | self.filepath_label.setText("None") 76 | 77 | def write_into_parser(self, parser): 78 | parser.add_section(constants.CONFIG_SECTION_ECLIPSE_TIMINGS) 79 | parser.set(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "iftime", str(self.iftime_chk.isChecked())) 80 | parser.set(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "cw", str(self.constant_weight_checkbox.isChecked())) 81 | parser.set(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "ksd", str(self.ksd_box.value())) 82 | parser.set(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "sigma", str(self.sigma_ipt.value())) 83 | parser.set(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "filepath", str(self.filepath_label.text())) 84 | 85 | return parser 86 | 87 | def read_from_parser(self, parser): 88 | self.clear_timings() 89 | 90 | self.iftime_chk.setChecked(parser.getboolean(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "iftime")) 91 | self.constant_weight_checkbox.setChecked(parser.getboolean(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "cw")) 92 | self.ksd_box.setValue(parser.getint(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "ksd")) 93 | self.sigma_ipt.setValue(parser.getfloat(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "sigma")) 94 | path = parser.get(constants.CONFIG_SECTION_ECLIPSE_TIMINGS, "filepath") 95 | 96 | if path != "None": 97 | self.load_timings(path) 98 | -------------------------------------------------------------------------------- /src/interfaces/history_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import history_widget 3 | from src.helpers.matplotlib_embedder import MatplotlibWidget 4 | from src import constants 5 | 6 | from matplotlib.ticker import MaxNLocator 7 | from src.helpers import methods 8 | from src.helpers import messenger 9 | 10 | 11 | delimiter = constants.EXPORT_DELIMITER 12 | 13 | 14 | class Widget(QtWidgets.QWidget, history_widget.Ui_HistoryWidget): 15 | def __init__(self, parent): 16 | super(Widget, self).__init__() 17 | self.setupUi(self) 18 | 19 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 20 | 21 | self.main_window = parent 22 | 23 | self.ptm_font = QtGui.QFont(parent.monoFont) 24 | self.ptm_font.setPointSize(9) 25 | self.history_treewidget.setFont(self.ptm_font) 26 | self.history_treewidget.header().setSectionResizeMode(3) 27 | 28 | header_item = QtWidgets.QTreeWidgetItem() 29 | header_item.setText(0, "Iteration #") 30 | header_item.setText(1, "Parameters") 31 | self.history_treewidget.setHeaderItem(header_item) 32 | 33 | self.chart = MatplotlibWidget(self.plot_widget, 2, 1, exportable=False) 34 | self.chart.create_axis(0, 0) 35 | self.chart.create_axis(1, 0) 36 | 37 | self.solutions = [] 38 | self.stats = [] 39 | 40 | self.connect_signals() 41 | 42 | def connect_signals(self): 43 | self.plot_btn.clicked.connect(self.plot_solutions) 44 | self.clear_btn.clicked.connect(self.clear) 45 | self.export_btn.clicked.connect(self.export_data) 46 | 47 | def export_data(self): 48 | if len(self.solutions) is not None: 49 | filepath = methods.save_file(self, suffix="txt") 50 | if filepath is not None: 51 | output = "# Itr" + delimiter 52 | for result in self.solutions[0]: 53 | output = output + constants.KEEPS_ID_NAME_DICT[result[0]] + delimiter + "adjustment" + delimiter +\ 54 | "error" + delimiter 55 | output = output + "MRfIV" + delimiter + "MRP" + delimiter + "\n" 56 | 57 | for idx, solution in enumerate(self.solutions): 58 | output = output + str(idx + 1) + delimiter 59 | for row in solution: 60 | output = output + str(row[4]) + delimiter + str(row[3]) + delimiter + str(row[5]) + delimiter 61 | 62 | output = output + str("{:0.16f}".format(self.stats[idx][0][0])) + delimiter + \ 63 | str("{:0.16f}".format(self.stats[idx][1][0])) + "\n" 64 | 65 | with open(filepath, "w") as destination: 66 | destination.write(output) 67 | 68 | msg = messenger.Messenger("info", "File saved:") 69 | msg.set_info(filepath) 70 | msg.show() 71 | 72 | def clear(self): 73 | self.chart.clear_all() 74 | self.solutions = [] 75 | self.stats = [] 76 | self.history_treewidget.clear() 77 | 78 | def selected_item(self): 79 | selecteditem = self.history_treewidget.selectedItems() 80 | if len(selecteditem) > 0: 81 | return selecteditem[0] 82 | else: 83 | return None 84 | 85 | def receive_solution(self, new_solution, new_stat): 86 | if len(self.solutions) == 0: 87 | self.solutions.append(new_solution) 88 | self.stats.append(new_stat) 89 | 90 | elif len(self.solutions[0]) == len(new_solution): 91 | same_solution = True 92 | old_solution = self.solutions[-1] 93 | for old, new in zip(old_solution, new_solution): 94 | if old[0] != new[0]: 95 | same_solution = False 96 | break 97 | 98 | if not same_solution: 99 | self.clear() 100 | self.solutions.append(new_solution) 101 | self.stats.append(new_stat) 102 | 103 | elif same_solution: 104 | self.solutions.append(new_solution) 105 | self.stats.append(new_stat) 106 | 107 | else: 108 | self.clear() 109 | self.solutions.append(new_solution) 110 | self.stats.append(new_stat) 111 | 112 | self.update_solutions() 113 | 114 | def update_solutions(self): 115 | if len(self.solutions) == 1: 116 | header_item = QtWidgets.QTreeWidgetItem() 117 | header_item.setText(0, "Itr #") 118 | for index, row in enumerate(self.solutions[0]): 119 | par_id = row[0] 120 | c_id = row[1] 121 | 122 | text = constants.KEEPS_ID_NAME_DICT[par_id] 123 | if c_id != 0.0: 124 | text = text + " (Curve #{0})".format(str(int(c_id))) 125 | header_item.setText(index + 1, text) 126 | #header_item.setText(index + 2, "Mean Residual for Input Values") 127 | self.history_treewidget.setHeaderItem(header_item) 128 | 129 | solution = self.solutions[-1] 130 | item = QtWidgets.QTreeWidgetItem(self.history_treewidget) 131 | item.setText(0, str(len(self.solutions))) 132 | for index, row in enumerate(solution): 133 | value = row[4] 134 | if row[0] in (19.0, 20.0): 135 | value = value * 10000.0 136 | item.setText(index + 1, "{:0.9f}".format(value)) 137 | #item.setText(index+2, "{:0.16f}".format(self.stats[-1][0][0])) 138 | 139 | if self.auto_chk.isChecked(): 140 | self.plot_solutions() 141 | 142 | def plot_solutions(self): 143 | selected_item = self.selected_item() 144 | if selected_item is not None and len(self.solutions) > 0: 145 | self.chart.clear_all() 146 | index = self.history_treewidget.currentColumn() - 1 147 | x = list(range(1, len(self.solutions) + 1)) 148 | y = [solution[index][4] for solution in self.solutions] 149 | y_w = [solution[index][5] for solution in self.solutions] 150 | 151 | y_s = [stat[0][0] for stat in self.stats] 152 | y_s2 = [stat[1][0] for stat in self.stats] 153 | 154 | if self.solutions[0][index][0] in (19.0, 20.0): 155 | _y = [yy * 10000.0 for yy in y] 156 | _y_w = [yyw * 10000.0 for yyw in y_w] 157 | 158 | y = _y 159 | y_w = _y_w 160 | 161 | self.chart.axes[0].errorbar(x, y, yerr=y_w, linestyle="-", marker="o", markersize=constants.MARKER_SIZE + 2, 162 | color=constants.COLOR_BLUE, ecolor=constants.COLOR_RED) 163 | self.chart.axes[0].set_ylabel(constants.KEEPS_ID_NAME_DICT[self.solutions[0][index][0]]) 164 | self.chart.axes[0].ticklabel_format(useOffset=False) 165 | self.chart.axes[0].get_yaxis().set_major_locator(MaxNLocator(integer=True)) 166 | self.chart.axes[1].plot(x, y_s, marker="o", markersize=constants.MARKER_SIZE + 2, 167 | color=constants.COLOR_BLUE) 168 | self.chart.axes[1].plot(x, y_s2, marker="o", markersize=constants.MARKER_SIZE + 2, 169 | color=constants.COLOR_RED) 170 | self.chart.axes[1].set_xlabel("Iteration Number") 171 | self.chart.axes[1].set_ylabel("Mean Residual\n (Input/Predicted)") 172 | self.chart.redraw() -------------------------------------------------------------------------------- /src/interfaces/lcdcpicker_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import lcdcpicker_dialog 3 | from src import constants 4 | from src.helpers import methods, messenger 5 | from functools import partial 6 | from configparser import ConfigParser, NoOptionError 7 | import os 8 | 9 | 10 | class Widget(QtWidgets.QDialog, lcdcpicker_dialog.Ui_LCDCPickerDialog): 11 | def __init__(self): 12 | super(Widget, self).__init__() 13 | self.setupUi(self) 14 | 15 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 16 | 17 | def _pick(label): 18 | path = methods.load_file(self) 19 | if path is not None: 20 | label.setText(path) 21 | label.setToolTip(path) 22 | 23 | self.picklc_btn.clicked.connect(partial(_pick, self.lcpath_label)) 24 | self.pickdc_btn.clicked.connect(partial(_pick, self.dcpath_label)) 25 | 26 | self.save_btn.clicked.connect(self.save) 27 | self.exit_btn.clicked.connect(self.exit) 28 | 29 | def check_config(self): 30 | if os.path.isfile(constants.PYWD_CONFIG_PATH): 31 | try: 32 | config = ConfigParser() 33 | config.read(constants.PYWD_CONFIG_PATH) 34 | lc_path = config.get("wd_paths", "lc_path") 35 | dc_path = config.get("wd_paths", "dc_path") 36 | 37 | if os.path.isfile(lc_path) and os.path.isfile(dc_path): 38 | self.lcpath_label.setText(lc_path) 39 | self.dcpath_label.setText(dc_path) 40 | return True 41 | 42 | else: 43 | msg = messenger.Messenger("warning", "Paths from the existing pywd_config file are not valid.") 44 | msg.set_info("Please reselect wd binary paths.") 45 | msg.show() 46 | return self.exec_() 47 | except NoOptionError as ex: 48 | msg = messenger.Messenger("error", "A NoOptionError occured during config file read.") 49 | msg.set_info("Config file is malformed. Please reselect wd binary paths.\nAdditional info:\n" + 50 | ex.args[0]) 51 | msg.show() 52 | return self.exec_() 53 | 54 | else: 55 | return self.exec_() 56 | 57 | def save(self): 58 | error = "" 59 | 60 | if os.path.isfile(self.lcpath_label.text()) is not True: 61 | error = "Can't find LC file in path:\n" + self.lcpath_label.text() 62 | 63 | if os.path.isfile(self.dcpath_label.text()) is not True: 64 | error = error + "\nCan't DC find file in path:\n" + self.dcpath_label.text() 65 | 66 | if error == "": 67 | config = ConfigParser() 68 | config.add_section("wd_paths") 69 | config.set("wd_paths", "lc_path", self.lcpath_label.text()) 70 | config.set("wd_paths", "dc_path", self.dcpath_label.text()) 71 | with open(constants.PYWD_CONFIG_PATH, "w") as f: 72 | config.write(f) 73 | 74 | self.accept() 75 | 76 | else: 77 | msg = messenger.Messenger("error", "Error(s) occured:") 78 | msg.set_info(error) 79 | msg.show() 80 | 81 | def exit(self): 82 | self.reject() 83 | -------------------------------------------------------------------------------- /src/interfaces/lineprofile_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import lineprofile_widget 3 | from src.helpers.matplotlib_embedder import MatplotlibWidget 4 | from src import constants 5 | from src.helpers.wd_utils import wd_io 6 | 7 | 8 | class Widget(QtWidgets.QWidget, lineprofile_widget.Ui_LineProfileWidget): 9 | def __init__(self, parent): 10 | super(Widget, self).__init__() 11 | self.setupUi(self) 12 | 13 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 14 | 15 | self.main_window = parent 16 | 17 | self.chart = MatplotlibWidget(self.plot_widget, 1, 1) 18 | self.chart.create_axis(0, 0, name="Spectral Line Profiles", labels=("Microns", "Norm. Flux")) 19 | 20 | self.s1_treewidget.header().setSectionResizeMode(1) 21 | self.s1_treewidget.header().setSectionsMovable(False) 22 | self.s2_treewidget.header().setSectionResizeMode(1) 23 | self.s2_treewidget.header().setSectionsMovable(False) 24 | 25 | self.connect_signals() 26 | 27 | def connect_signals(self): 28 | self.plot_btn.clicked.connect(self.plot_lines) 29 | self.s1_add_btn.clicked.connect(self.add_row_to_primary) 30 | self.s2_add_btn.clicked.connect(self.add_row_to_secondary) 31 | self.s1_remove_btn.clicked.connect(self.remove_row_from_primary) 32 | self.s2_remove_btn.clicked.connect(self.remove_row_from_secondary) 33 | 34 | def add_row_to_primary(self): 35 | self.add_row(self.s1_treewidget) 36 | 37 | def add_row_to_secondary(self): 38 | self.add_row(self.s2_treewidget) 39 | 40 | def remove_row_from_primary(self): 41 | self.remove_row(self.s1_treewidget) 42 | 43 | def remove_row_from_secondary(self): 44 | self.remove_row(self.s2_treewidget) 45 | 46 | def get_selected(self, widget): 47 | selected_items = widget.selectedItems() 48 | if len(selected_items) > 0: 49 | return selected_items[0] 50 | else: 51 | return None 52 | 53 | def add_row(self, widget): 54 | item = QtWidgets.QTreeWidgetItem(widget) 55 | i = 0 56 | values = [0.65627, 0.00001, 0.5] 57 | while i < 3: 58 | spinbox = QtWidgets.QDoubleSpinBox(widget) 59 | spinbox.setButtonSymbols(2) 60 | spinbox.setDecimals(7) 61 | spinbox.setMaximum(999) 62 | spinbox.setMinimum(0) 63 | spinbox.setValue(values[i]) 64 | widget.setItemWidget(item, i, spinbox) 65 | i = i + 1 66 | 67 | integer_spinbox = QtWidgets.QSpinBox(widget) 68 | integer_spinbox.setButtonSymbols(2) 69 | integer_spinbox.setMinimum(-999) 70 | integer_spinbox.setMaximum(999) 71 | integer_spinbox.setValue(0) 72 | widget.setItemWidget(item, 3, integer_spinbox) 73 | 74 | def remove_row(self, widget): 75 | selected_item = self.get_selected(widget) 76 | if selected_item is not None: 77 | widget.headerItem().removeChild(selected_item) 78 | 79 | def plot_lines(self): 80 | self.chart.clear_all() 81 | 82 | lc_params = self.main_window.get_lc_params() 83 | 84 | lc_params["binwm1"] = self.s1_binwidth_spinbox.value() 85 | lc_params["sc1"] = self.s1_contscale_spinbox.value() 86 | lc_params["sl1"] = self.s1_contslope_spinbox.value() 87 | lc_params["nf1"] = self.s1_subgrid_spinbox.value() 88 | 89 | lc_params["binwm2"] = self.s2_binwidth_spinbox.value() 90 | lc_params["sc2"] = self.s2_contscale_spinbox.value() 91 | lc_params["sl2"] = self.s2_contslope_spinbox.value() 92 | lc_params["nf2"] = self.s2_subgrid_spinbox.value() 93 | 94 | # def add_spectral_line(self, star, wll, ewid, depth, kks): 95 | 96 | s1_child_count = self.s1_treewidget.invisibleRootItem().childCount() 97 | index = 0 98 | while index < s1_child_count: 99 | item = self.s1_treewidget.invisibleRootItem().child(index) 100 | lc_params.add_spectral_line( 101 | 1, 102 | self.s1_treewidget.itemWidget(item, 0).value(), 103 | self.s1_treewidget.itemWidget(item, 1).value(), 104 | self.s1_treewidget.itemWidget(item, 2).value(), 105 | self.s1_treewidget.itemWidget(item, 3).value() 106 | ) 107 | 108 | index = index + 1 109 | 110 | s2_child_count = self.s2_treewidget.invisibleRootItem().childCount() 111 | index = 0 112 | while index < s2_child_count: 113 | item = self.s2_treewidget.invisibleRootItem().child(index) 114 | lc_params.add_spectral_line( 115 | 2, 116 | self.s2_treewidget.itemWidget(item, 0).value(), 117 | self.s2_treewidget.itemWidget(item, 1).value(), 118 | self.s2_treewidget.itemWidget(item, 2).value(), 119 | self.s2_treewidget.itemWidget(item, 3).value() 120 | ) 121 | 122 | index = index + 1 123 | 124 | lc_params["jdphs"] = 2 125 | lc_params["phstrt"] = self.phase_spinbox.value() 126 | lc_params["phstop"] = self.phase_spinbox.value() 127 | lc_params["phin"] = 0.1 128 | 129 | lc_io = wd_io.LCIO(lc_params, 130 | wd_path=self.main_window.lc_path, 131 | lc_binary_name=self.main_window.lc_binary) 132 | 133 | s1_results, s2_results = lc_io.fill_for_spectral_lines().save().run().read_spectral_lines() 134 | 135 | if len(s1_results[0]) > 0: 136 | self.chart.plot(s1_results[0][2], s1_results[0][4], color=constants.COLOR_BLUE) 137 | 138 | if len(s2_results[0]) > 0: 139 | self.chart.plot(s2_results[0][2], s2_results[0][4], clear=False, color=constants.COLOR_RED) 140 | 141 | def clear(self): 142 | self.chart.clear_all() 143 | -------------------------------------------------------------------------------- /src/interfaces/loadobservations_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import loadobservations_widget 3 | from . import curveproperties_interface 4 | from matplotlib import pyplot 5 | import os 6 | from src import constants 7 | 8 | 9 | class Widget(QtWidgets.QWidget, loadobservations_widget.Ui_ObservationWidget): 10 | def __init__(self, main_window): 11 | super(Widget, self).__init__() 12 | self.setupUi(self) 13 | 14 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 15 | 16 | self.main_window = main_window 17 | 18 | self.velocity_curves = [None, None] 19 | self.light_curves = [] 20 | 21 | self.curve_treewidget.header().setSectionResizeMode(3) 22 | 23 | self.connect_signals() 24 | 25 | def connect_signals(self): 26 | self.add_btn.clicked.connect(self.add_observation) 27 | self.edit_btn.clicked.connect(self.edit_observation) 28 | self.remove_btn.clicked.connect(self.remove_observation) 29 | self.plot_btn.clicked.connect(self.plot_observation) 30 | 31 | def selected_item(self): 32 | selected_item = self.curve_treewidget.selectedItems() 33 | if len(selected_item) > 0: 34 | return selected_item[0] 35 | else: 36 | return None 37 | 38 | def add_observation(self): 39 | menu = QtWidgets.QMenu(self) 40 | 41 | # vc menu 42 | addvc = QtWidgets.QMenu("Velocity Curve") 43 | menu.addMenu(addvc) 44 | pri = addvc.addAction("Primary") 45 | pri.setObjectName("primary") 46 | sec = addvc.addAction("Secondary") 47 | sec.setObjectName("secondary") 48 | 49 | if self.velocity_curves[0] is not None: 50 | pri.setDisabled(True) 51 | 52 | if self.velocity_curves[1] is not None: 53 | sec.setDisabled(True) 54 | 55 | # lc action 56 | addlc = menu.addAction("Light Curve") 57 | addlc.setObjectName("lightcurve") 58 | 59 | selection = menu.exec_(QtGui.QCursor.pos()) 60 | 61 | if selection is not None: 62 | curve_type = "" 63 | if selection.objectName() == "primary" or selection.objectName() == "secondary": 64 | curve_type = curveproperties_interface.TYPE_VELOCITY 65 | elif selection.objectName() == "lightcurve": 66 | curve_type = curveproperties_interface.TYPE_LIGHT 67 | 68 | curve = curveproperties_interface.CurveProperty(curve_type, self.main_window) 69 | curve.show_dialog() 70 | 71 | if curve.unpopulated is not True: 72 | if selection.objectName() == "primary": 73 | self.velocity_curves[0] = curve 74 | elif selection.objectName() == "secondary": 75 | self.velocity_curves[1] = curve 76 | elif selection.objectName() == "lightcurve": 77 | self.light_curves.append(curve) 78 | 79 | self.update_curve_list() 80 | 81 | def edit_observation(self): 82 | item = self.selected_item() 83 | if item is not None: 84 | if item.text(1) == "Velocity Curve (Star 1)": 85 | self.velocity_curves[0].edit() 86 | 87 | elif item.text(1) == "Velocity Curve (Star 2)": 88 | self.velocity_curves[1].edit() 89 | 90 | elif item.text(1) == "Light Curve": 91 | index = self.curve_treewidget.invisibleRootItem().indexOfChild(item) 92 | 93 | if self.velocity_curves[0] is not None: 94 | index = index - 1 95 | 96 | if self.velocity_curves[1] is not None: 97 | index = index - 1 98 | 99 | self.light_curves[index].edit() 100 | 101 | self.update_curve_list() 102 | 103 | def remove_observation(self): 104 | item = self.selected_item() 105 | if item is not None: 106 | if item.text(1) == "Velocity Curve (Star 1)": 107 | self.velocity_curves[0] = None 108 | 109 | elif item.text(1) == "Velocity Curve (Star 2)": 110 | self.velocity_curves[1] = None 111 | 112 | elif item.text(1) == "Light Curve": 113 | index = self.curve_treewidget.invisibleRootItem().indexOfChild(item) 114 | 115 | if self.velocity_curves[0] is not None: 116 | index = index - 1 117 | 118 | if self.velocity_curves[1] is not None: 119 | index = index - 1 120 | 121 | self.light_curves.pop(index) 122 | 123 | self.update_curve_list() 124 | 125 | def plot_observation(self): 126 | item = self.selected_item() 127 | curve = None 128 | if item is not None: 129 | if item.text(1) == "Velocity Curve (Star 1)": 130 | curve = self.velocity_curves[0] 131 | 132 | elif item.text(1) == "Velocity Curve (Star 2)": 133 | curve = self.velocity_curves[1] 134 | 135 | elif item.text(1) == "Light Curve": 136 | index = self.curve_treewidget.invisibleRootItem().indexOfChild(item) 137 | 138 | if self.velocity_curves[0] is not None: 139 | index = index - 1 140 | 141 | if self.velocity_curves[1] is not None: 142 | index = index - 1 143 | 144 | curve = self.light_curves[index] 145 | 146 | x, y, z = curve.get_data() 147 | 148 | pyplot.plot(x, y, linestyle="", marker="o", markersize=2, color=constants.COLOR_BLUE) 149 | pyplot.get_current_fig_manager().set_window_title("Matplotlib - " + item.text(0)) 150 | if str(self.main_window.maglite_combobox.currentText()) == "Magnitude" and str(item.text(1)) == "Light Curve": 151 | pyplot.gca().invert_yaxis() 152 | pyplot.show() 153 | 154 | def update_curve_list(self): 155 | self.curve_treewidget.clear() 156 | 157 | if self.velocity_curves[0] is not None: 158 | itm = QtWidgets.QTreeWidgetItem(self.curve_treewidget) 159 | itm.setText(0, os.path.basename(self.velocity_curves[0].filepath)) 160 | itm.setText(1, "Velocity Curve (Star 1)") 161 | itm.setText(2, " - ") 162 | # itm.setText(2, constants.ID_BANDPASS_DICT[str(self.velocity_curves[0].band_id)]) 163 | 164 | if self.velocity_curves[1] is not None: 165 | itm = QtWidgets.QTreeWidgetItem(self.curve_treewidget) 166 | itm.setText(0, os.path.basename(self.velocity_curves[1].filepath)) 167 | itm.setText(1, "Velocity Curve (Star 2)") 168 | itm.setText(2, " - ") 169 | # itm.setText(2, constants.ID_BANDPASS_DICT[str(self.velocity_curves[1].band_id)]) 170 | 171 | for light_curve in self.light_curves: 172 | itm = QtWidgets.QTreeWidgetItem(self.curve_treewidget) 173 | itm.setText(0, os.path.basename(light_curve.filepath)) 174 | itm.setText(1, "Light Curve") 175 | itm.setText(2, constants.ID_BANDPASS_DICT[str(light_curve.band_id)]) 176 | 177 | self.main_window.curve_list_changed() 178 | 179 | def write_into_parser(self, parser): 180 | parser.add_section(constants.CONFIG_SECTION_CURVE_COUNTS) 181 | parser.set(constants.CONFIG_SECTION_CURVE_COUNTS, "light_curves", str(len(self.light_curves))) 182 | 183 | i = 1 184 | for light_curve in self.light_curves: 185 | section = constants.CONFIG_SECTION_LIGHT_CURVE_STUB + str(i) 186 | parser.add_section(section) 187 | parser = light_curve.populate_parser(parser, section) 188 | i = i + 1 189 | 190 | if self.velocity_curves[0] is not None: 191 | parser.set(constants.CONFIG_SECTION_CURVE_COUNTS, "velocity_curve_1", str(True)) 192 | 193 | section = constants.CONFIG_SECTION_VELOCITY_CURVE_STUB + "1" 194 | parser.add_section(section) 195 | parser = self.velocity_curves[0].populate_parser(parser, section) 196 | 197 | else: 198 | parser.set(constants.CONFIG_SECTION_CURVE_COUNTS, "velocity_curve_1", str(False)) 199 | 200 | if self.velocity_curves[1] is not None: 201 | parser.set(constants.CONFIG_SECTION_CURVE_COUNTS, "velocity_curve_2", str(True)) 202 | 203 | section = constants.CONFIG_SECTION_VELOCITY_CURVE_STUB + "2" 204 | parser.add_section(section) 205 | parser = self.velocity_curves[1].populate_parser(parser, section) 206 | 207 | else: 208 | parser.set(constants.CONFIG_SECTION_CURVE_COUNTS, "velocity_curve_2", str(False)) 209 | 210 | return parser 211 | 212 | def read_from_parser(self, parser): 213 | 214 | self.velocity_curves = [None, None] 215 | self.light_curves = [] 216 | 217 | if parser.getboolean(constants.CONFIG_SECTION_CURVE_COUNTS, "velocity_curve_1") is True: 218 | curve = curveproperties_interface.CurveProperty(curveproperties_interface.TYPE_VELOCITY, self.main_window) 219 | curve.populate_from_parser(parser, constants.CONFIG_SECTION_VELOCITY_CURVE_STUB + "1") 220 | self.velocity_curves[0] = curve 221 | 222 | if parser.getboolean(constants.CONFIG_SECTION_CURVE_COUNTS, "velocity_curve_2") is True: 223 | curve = curveproperties_interface.CurveProperty(curveproperties_interface.TYPE_VELOCITY, self.main_window) 224 | curve.populate_from_parser(parser, constants.CONFIG_SECTION_VELOCITY_CURVE_STUB + "2") 225 | self.velocity_curves[1] = curve 226 | 227 | lc_count = parser.getint(constants.CONFIG_SECTION_CURVE_COUNTS, "light_curves") 228 | i = 1 229 | 230 | while i <= lc_count: 231 | curve = curveproperties_interface.CurveProperty(curveproperties_interface.TYPE_LIGHT, self.main_window) 232 | curve.populate_from_parser(parser, constants.CONFIG_SECTION_LIGHT_CURVE_STUB + str(i)) 233 | self.light_curves.append(curve) 234 | i = i + 1 235 | 236 | self.update_curve_list() 237 | 238 | def get_all_curves(self): 239 | curves = [] 240 | 241 | if self.velocity_curves[0] is not None: 242 | curves.append(self.velocity_curves[0]) 243 | 244 | if self.velocity_curves[1] is not None: 245 | curves.append(self.velocity_curves[1]) 246 | 247 | for light_curve in self.light_curves: 248 | curves.append(light_curve) 249 | 250 | return curves 251 | -------------------------------------------------------------------------------- /src/interfaces/oc_interface.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import oc_widget 3 | from src.helpers.matplotlib_embedder import MatplotlibWidget 4 | from src import constants 5 | import os 6 | from src.helpers import messenger 7 | from src.helpers.wd_utils import wd_io 8 | import numpy 9 | from src.helpers import methods 10 | 11 | 12 | delimiter = constants.EXPORT_DELIMITER 13 | 14 | 15 | class Widget(QtWidgets.QWidget, oc_widget.Ui_OCWidget): 16 | def __init__(self, parent): 17 | super(Widget, self).__init__() 18 | self.setupUi(self) 19 | 20 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 21 | 22 | self.main_window = parent 23 | 24 | self.chart = MatplotlibWidget(self.plot_widget, 1, 1, exportable=False) 25 | self.chart.create_axis(0, 0, name="", labels=("E", "O - C (Day)")) 26 | 27 | self.data_treewidget.setFont(parent.monoFont) 28 | self.data_treewidget.header().setSectionResizeMode(3) 29 | 30 | self.cycles = [] 31 | self.linear_resid = [] 32 | self.dpdt_resid = [] 33 | 34 | self.connect_signals() 35 | 36 | def connect_signals(self): 37 | self.compute_btn.clicked.connect(self.compute_oc) 38 | self.dpdt_chk.toggled.connect(self.update_plots) 39 | self.linear_chk.toggled.connect(self.update_plots) 40 | self.calculate_btn.clicked.connect(self.calculate_dp_and_dt) 41 | self.update_btn.clicked.connect(self.update_ephemeris_and_period) 42 | self.export_btn.clicked.connect(self.export_data) 43 | 44 | def export_data(self): 45 | root = self.data_treewidget.invisibleRootItem() 46 | if root.childCount() == 0: 47 | return 1 48 | 49 | filepath = methods.save_file(self, suffix="txt") 50 | if filepath is not None: 51 | lenght = 3 52 | output = "# HJD" + delimiter + "Linear Residuals" + delimiter + "Residuals with dP/dt\n" 53 | 54 | root = self.data_treewidget.invisibleRootItem() 55 | i = 0 56 | while i < root.childCount(): 57 | idx = 0 58 | while idx < lenght: 59 | output = output + root.child(i).text(idx) + delimiter 60 | idx = idx + 1 61 | 62 | output = output + "\n" 63 | i = i + 1 64 | 65 | with open(filepath, "w") as destination: 66 | destination.write(output) 67 | 68 | msg = messenger.Messenger("info", "File saved:") 69 | msg.set_info(filepath) 70 | msg.show() 71 | 72 | def compute_oc(self): 73 | eclipse_timings_path = self.main_window.eclipsetimings_widget.filepath_label.text() 74 | if os.path.isfile(eclipse_timings_path): 75 | 76 | self.clear() 77 | 78 | lc_params = self.main_window.get_lc_params() 79 | 80 | ec_data = numpy.loadtxt(eclipse_timings_path, unpack=True) 81 | lc_params.add_eclipse_times(ec_data[0], ec_data[1]) 82 | 83 | lc_io = wd_io.LCIO(lc_params, 84 | wd_path=self.main_window.lc_path, 85 | lc_binary_name=self.main_window.lc_binary) 86 | 87 | results = lc_io.fill_for_etv().save().run().read_etv() 88 | 89 | i = 0 90 | while i < len(results[0]): 91 | jd = results[0][i] 92 | lin_res = results[3][i] 93 | dpdt_res = results[5][i] 94 | 95 | item = QtWidgets.QTreeWidgetItem(self.data_treewidget) 96 | item.setText(0, str(jd)) 97 | item.setText(1, str(lin_res)) 98 | item.setText(2, str(dpdt_res)) 99 | 100 | i = i + 1 101 | 102 | t0 = self.main_window.jd0_ipt.value() 103 | p = self.main_window.p0_ipt.value() 104 | 105 | for t in results[0]: 106 | cycle = (t - t0) / p 107 | e = numpy.around(cycle * 2.0, decimals=0) / 2.0 108 | self.cycles.append(e) 109 | 110 | self.linear_resid = results[3] 111 | self.dpdt_resid = results[5] 112 | 113 | self.update_plots() 114 | 115 | else: 116 | msg = messenger.Messenger("error", "An eclipse timings file must be provided for O - C calculation.") 117 | msg.set_info("You can load eclipse timings from the main tab.") 118 | msg.show() 119 | 120 | def update_plots(self): 121 | self.chart.clear_all() 122 | 123 | if self.linear_chk.isChecked(): 124 | self.chart.plot(self.cycles, self.linear_resid, clear=False, 125 | markersize=2, marker="o", linestyle="", color=constants.COLOR_BLUE) 126 | 127 | if self.dpdt_chk.isChecked(): 128 | self.chart.plot(self.cycles, self.dpdt_resid, clear=False, 129 | markersize=2, marker="o", linestyle="", color=constants.COLOR_RED) 130 | 131 | def calculate_dp_and_dt(self): 132 | if len(self.cycles) != 0 and self.linear_chk.isChecked(): 133 | 134 | model_coeffs = numpy.polyfit(self.cycles, self.linear_resid, 1) 135 | model_y = [(y * model_coeffs[0] + model_coeffs[1]) for y in self.cycles] 136 | 137 | self.dp_otpt.setValue(model_coeffs[0]) 138 | self.dt_otpt.setValue(model_coeffs[1]) 139 | 140 | self.chart.plot(self.cycles, model_y, clear=False, color=constants.COLOR_RED) 141 | 142 | def update_ephemeris_and_period(self): 143 | if len(self.cycles) != 0: 144 | self.main_window.jd0_ipt.setValue(self.main_window.jd0_ipt.value() + self.dt_otpt.value()) 145 | self.main_window.p0_ipt.setValue(self.main_window.p0_ipt.value() + self.dp_otpt.value()) 146 | 147 | self.update_plots() 148 | 149 | self.dp_otpt.setValue(0.0) 150 | self.dt_otpt.setValue(0.0) 151 | 152 | self.compute_btn.click() 153 | 154 | def clear(self): 155 | self.cycles = [] 156 | self.linear_resid = [] 157 | self.dpdt_resid = [] 158 | 159 | self.chart.clear_all() 160 | self.data_treewidget.clear() 161 | self.dp_otpt.setValue(0.0) 162 | self.dt_otpt.setValue(0.0) 163 | -------------------------------------------------------------------------------- /src/interfaces/single_conjunction.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtGui 2 | from gui import single_conjunction 3 | from src import constants 4 | from src.helpers import methods 5 | 6 | 7 | class Widget(QtWidgets.QWidget, single_conjunction.Ui_ConjunctionWidget): 8 | def __init__(self, parent): 9 | super(Widget, self).__init__() 10 | self.setupUi(self) 11 | 12 | self.setWindowIcon(QtGui.QIcon(constants.MAIN_ICON_PATH)) 13 | 14 | self.main_window = parent 15 | 16 | self.conj_btn.clicked.connect(self.compute_conjunctions) 17 | 18 | def compute_conjunctions(self): 19 | w = self.main_window.perr0_ipt.value() 20 | e = self.main_window.e_ipt.value() 21 | phase_shift = self.main_window.pshift_ipt.value() 22 | 23 | conjunctions = methods.compute_conjunction_phases(w, e, phase_shift) 24 | 25 | primary_eclipse, first_quadrature, secondary_eclipse, second_quadrature, periastron, apastron = conjunctions 26 | 27 | self.prieclipse_opt.setText("{:0.8f}".format(primary_eclipse)) 28 | self.firstquad_opt.setText("{:0.8f}".format(first_quadrature)) 29 | self.sececlipse_opt.setText("{:0.8f}".format(secondary_eclipse)) 30 | self.secondquad_opt.setText("{:0.8f}".format(second_quadrature)) 31 | self.periastron_opt.setText("{:0.8f}".format(periastron)) 32 | self.apastron_opt.setText("{:0.8f}".format(apastron)) 33 | --------------------------------------------------------------------------------