Esempio n. 1
0
    def spectrum(self,
                 in_date,
                 in_time,
                 binning=2,
                 binning_method='avg',
                 plot=True,
                 out_image="singletimespectrum.png",
                 return_data=False,
                 fig_size=(8, 6),
                 font_size=14,
                 grid=True):
        """
        Plot the spectrum for a given time, i.e. amplitude at all frequencies at given time

        Input arguments:
            indate :date to plot spectrum of,
                    should be a python datetime object or
                    string of format 'YYYY/MM/DD'
            intime : time to plot spectrum of,
                    should be a python datetime.time object or
                    string of format 'HH:MM:SS'
            binning: pixel-level binning while selecting a row (default = 2)
                caution, only advanced users should alter this parameter
            binnigmethod : either of avg, sum, med (default = 'avg')
            plot (Boolean) : plot it or not, Default True
            outimage : Name of the image to save, default is "singletimespectrum.png"
            returndata (Boolean) :   default False
            figsize: size of the fig (default = (8, 8))
            font_size: font_size of the used in plots (default =14)
            grid: to plot agrid or not (default = True)

        returns:if returndata is set to True
                return a tuple of (bintbl_freq_data, spectrum)
                where
                    bintbl_freq_data :  list of frequencies
                    spectrum :  intensity count at these respective ffrequencies

        """

        # open input fits file
        hdus = self.hdus
        image_hdu = hdus[0]
        bin_table_hdu = hdus[1]
        image_header = image_hdu.header
        image_data = image_hdu.data
        bintbl_freq_data = bin_table_hdu.data[0][1]
        bintbl_freq_data = bin_table_hdu.data[0][1]

        # get startdate-time and enddate-time of the file
        start_date = utils.to_date(image_header['DATE-OBS'])
        start_time = utils.to_time(image_header['TIME-OBS'])
        start_time = dt.datetime.combine(start_date,
                                         start_time)  # make a datetime object
        end_time = utils.to_time(image_header['TIME-END'])
        end_time = dt.datetime.combine(start_date, end_time)
        # check the format of in date and intime

        if isinstance(in_date, dt.date) and isinstance(in_time, dt.time):
            in_date_time = dt.datetime.combine(in_date, in_time)
        else:
            if isinstance(in_date, str) and isinstance(in_time, str):
                if len(in_date.split('/')) == 3:
                    # year, month, day = indate.split('/')
                    in_date = utils.to_date(in_date)
                else:
                    raise Exception("Date string not in proper format")

                if len(in_time.split(':')) == 3:
                    # hr, mint, sec = intime.split(':')
                    in_time = utils.to_time(in_time)
                else:
                    raise Exception("Time string not in proper format")
                in_date_time = dt.datetime.combine(in_date, in_time)
            else:
                raise Exception("Date and/or time not in proper format")

        # check input time
        if in_date_time < start_time or in_date_time > end_time:
            print("Provided datetime is " + str(in_date_time))
            print("Start datetime for this file is " + str(start_time))
            print("End datetime for this file is" + str(end_time))
            raise Exception(
                "Input time is out of limit for this data, aborting the operation"
            )

        # get the columnnumber of given datetime in a image_data
        def get_time_axis(start, end, delta):
            curr = start
            while curr < end:
                yield curr
                curr += delta

        time_axis = [
            time for time in get_time_axis(start_time, end_time, (end_time -
                                                                  start_time) /
                                           image_data.shape[1])
        ]

        time_index = time_axis.index(in_date_time)
        spectrum = image_data[:, time_index - binning:time_index + binning + 1]

        # print(spectrum.shape)
        if binning_method == 'med':
            spectrum = np.median(spectrum, axis=1)
        if binning_method == 'sum':
            spectrum = spectrum.sum(axis=1)
        if binning_method == 'avg':
            spectrum = np.average(spectrum, axis=1)

        if plot:
            plt.clf()
            fig, ax = plt.subplots(figsize=(fig_size[0], fig_size[1]))
            ax.plot_date(bintbl_freq_data, spectrum, 'b-', xdate=True)
            ticks = list(
                np.linspace(bintbl_freq_data[-1], bintbl_freq_data[0],
                            20).astype('int'))  # calcult 200 ticks positions
            plt.xticks(ticks, ticks, rotation=45)
            # ax.xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
            plt.xlabel('Frequency (MHz)', fontSize=font_size)
            plt.ylabel('Amplitude', fontSize=font_size)
            # title = infits + "\n" + image_header['DATE-OBS'] + "::" + image_header['TIME-OBS']
            # title = self.image_header['CONTENT']
            title = "Spectrum - " + str(in_date_time)
            plt.title(title)
            if grid:
                plt.grid()
            plt.savefig(out_image)

        else:
            if return_data:
                return bintbl_freq_data, spectrum
Esempio n. 2
0
    def universal_plot(self,
                       plot_name="universal_plot_with_add_processing.png",
                       title='Universal Plot',
                       return_plot=False,
                       xtick=3,
                       ytick=3,
                       end_pts=[False, False],
                       blevel=0,
                       fig_size=(10, 8),
                       cmap=cm.jet,
                       label_font_size=10,
                       title_font_size=14,
                       color_bar=True,
                       color_bar_ori='horizontal'):
        """
        plot universal plot


        input arguments:
            plot_name: name of the image to be saved
            title: title of plot
            return_plot: to return matplotlib plot object or not (defayult = False)
            xtick: frequency of xticks in minutes (default = 3)
            ytick: frequency of yticks in minutes (default = 3)
            end_pts:	plot endpoints on x and y axis irrespective of ticks (fefault= (False, false))
            blevel: background level (default = 0)
            fig_size:  tuple representing size of image (default = (8,6))
            cmap: a matplotlib colormap object (default = cm.jet)
            label_font_size: font_size used in plot for labels (default = 10)
            title_font_size: font_size used in plot for title (default = 14)
            color_bar: to plot a colorbar or not (default = true)
            color_bar_ori: colorbar orientation (default = 'vertical')
        """

        # create global plot object with subplot
        fig = plt.figure(figsize=(fig_size[0], fig_size[1]))

        # plot the spectrogram in the one subplot
        ax1 = plt.subplot2grid(shape=(8, 8), loc=(0, 0), rowspan=5, colspan=5)

        # get the start time and end time of observation
        start_date = utils.to_date(self.imageHeader['DATE-OBS'])
        start_time = utils.to_time(self.imageHeader['TIME-OBS'])

        start_time = dt.datetime.combine(start_date,
                                         start_time)  # make a datetime object
        end_time = utils.to_time(self.imageHeader['TIME-END'])
        end_time = dt.datetime.combine(start_date, end_time)

        # get the frequencies
        freqs = self.binTableHdu.data['frequency'][
            0]  # these are true frequencies

        # set the limits for plotting
        x_lims = [start_time, end_time]
        x_lims = mdates.date2num(x_lims)  # dates to numeric values
        y_lims = [freqs[-1], freqs[0]]

        im1 = ax1.imshow(self.imageHdu.data,
                         extent=[x_lims[0], x_lims[1], y_lims[0], y_lims[1]],
                         aspect='auto',
                         cmap=cmap,
                         vmin=blevel)

        # set ytick labels to be intigers only, in case we have a small frequency range, pyplot tends to show fraction
        ax1.get_yaxis().get_major_formatter().set_useOffset(False)
        plt.minorticks_on()

        if end_pts[0]:
            # get the start time and end time ans set ticks at those position son x-axis using minor_locator
            total_sec = utils.tosec(end_time - start_time)
            ax1.xaxis.set_minor_locator(
                mdates.SecondLocator(bysecond=None,
                                     interval=total_sec,
                                     tz=None))
            ax1.xaxis.set_minor_formatter(DateFormatter('%H:%M:%S'))
        fig.autofmt_xdate()

        if end_pts[1]:
            # set y minorticks for first and last frequency
            plt.yticks(list(plt.yticks()[0]) + y_lims)

        # plt.xlabel('Universal Time')
        plt.ylabel('Frequency (MHz)', fontSize=label_font_size)

        ax1.tick_params(direction='in', axis='both', which='both')
        ax1.yaxis.set_ticks_position('both')
        ax1.xaxis.set_ticks_position('both')
        ax1.tick_params(labelbottom=False)

        ax2 = plt.subplot2grid(shape=(8, 8),
                               loc=(5, 0),
                               rowspan=3,
                               colspan=5,
                               sharex=ax1)

        # use meanlightcurve to get the lightcurve data
        data = self.mean_light_curve(plot=False, return_data=True)
        sum_image, time_in_sec, time_axis = data

        plt.minorticks_on()
        plt.xticks(rotation=45)
        ax2.plot(time_axis, sum_image, 'k')
        ax2.tick_params(direction='in', axis='both', which='both')
        ax2.yaxis.set_ticks_position('both')
        ax2.xaxis.set_ticks_position('both')
        ax2.margins(0.0)
        ax2.set_xlabel('Universal Time')

        # define ax3
        ax3 = plt.subplot2grid(shape=(8, 8),
                               loc=(0, 5),
                               rowspan=5,
                               colspan=3,
                               sharey=ax1)
        # use meanspectrum to get spectrum data
        data = self.mean_spectrum(plot=False, return_data=True)
        sum_image, bintblfreqdata = data
        # use spectrum data to plot spectrum in third subplot
        ax3.plot(sum_image, bintblfreqdata, 'k')
        plt.minorticks_on()
        ax3.tick_params(direction='in', axis='both', which='both')
        ax3.yaxis.set_ticks_position('both')
        ax3.xaxis.set_ticks_position('both')
        ax3.tick_params(labelleft=False)
        ax3.tick_params(labelright=True)
        ax3.invert_xaxis()
        plt.xticks(rotation=45)
        ax3.margins(0.0)

        plt.suptitle(title, fontsize=title_font_size + 4)
        fig.subplots_adjust(right=0.8)
        cbar_ax = fig.add_axes([0.85, 0.15, 0.03, 0.7])
        fig.colorbar(im1, cax=cbar_ax)
        plt.savefig(plot_name)
Esempio n. 3
0
    def light_curve(self,
                    frequency,
                    plot=True,
                    out_image="Lightcurve.png",
                    return_data=False,
                    fig_size=(8, 8),
                    font_size=14,
                    grid=True):
        """
        Plot the lightcurve for given frequency, i.e. time vs amplitude, or return the data

        Input arguments:
            frequency: frequency to plot lightcurve
            plot (Boolean): plot it or not (Default = True)
            out_image: Name of the image to save, default is "Lightcurve.png"
            return_data (Boolean) : return the data or not (default = False)
            figsize: size of the fig (default = (8, 8))
            font_size: font_size of the used in plots (default =14)
            grid: to plot agrid or not (default = True)
        returns:if return_data is set to True
#				return a tuple of (time_axis, light_curve)
                where
                    time_axis is array of python dataetime object
                    light_curve is numpy array
        """

        # open input fits file
        hdus = self.hdus
        image_hdu = hdus[0]
        bin_table_hdu = hdus[1]
        image_header = image_hdu.header
        image_data = image_hdu.data
        # bintbl_freq_data = bin_table_hdu.data[0][1]
        bintbl_freq_data = bin_table_hdu.data[0][1]

        # check input frequency
        start_freq = int(bintbl_freq_data[-1])
        end_freq = int(bintbl_freq_data[0])
        if frequency < start_freq or frequency > end_freq:
            raise Exception(
                "Input frequency is out of limit for this data, aborting the operation"
            )

        # get the nearest value in the bintable to the user input frequency
        min_diff = (np.abs(bintbl_freq_data - frequency)).min()
        idx = (np.abs(bintbl_freq_data - frequency)).argmin()
        nearest_frequency = bintbl_freq_data[idx]

        # give warning if the difference between input frequency and the nearest frequency is greater than 5
        if min_diff > 5:
            print(
                "Please note that the difference between demanded frequency and the nearest one in data is %g"
                % min_diff)

        # get the corresponding row from image_data
        light_curve = image_data[idx, :]

        # get startdate-time and enddate-time
        start_date = utils.to_date(image_header['DATE-OBS'])
        start_time = utils.to_time(image_header['TIME-OBS'])
        start_time = dt.datetime.combine(start_date,
                                         start_time)  # make a datetime object
        end_time = utils.to_time(image_header['TIME-END'])
        end_time = dt.datetime.combine(start_date, end_time)

        def get_time_axis(start, end, delta):
            curr = start
            while curr < end:
                yield curr
                curr += delta

        time_axis = [
            time for time in get_time_axis(start_time, end_time, (end_time -
                                                                  start_time) /
                                           light_curve.shape[0])
        ]

        if plot:
            plt.clf()
            fig, ax = plt.subplots(figsize=(fig_size[0], fig_size[1]))
            ax.plot_date(time_axis, light_curve, 'b-', xdate=True)
            ax.xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
            plt.xticks(rotation=45)

            plt.xlabel('Universal Time', fontSize=font_size)
            plt.ylabel('Amplitude', fontSize=font_size)
            # title = infits + "\n" + image_header['DATE-OBS'] + "::" + image_header['TIME-OBS']
            # title = self.image_header['CONTENT']
            title = "Light curve - " + str(round(nearest_frequency,
                                                 2)) + " MHz"
            plt.title(title, fontSize=font_size)
            if grid:
                plt.grid()
            plt.savefig(out_image)
        else:
            if return_data:
                return time_axis, light_curve
Esempio n. 4
0
    def mean_light_curve(self,
                         plot=True,
                         out_image="timeseries.png",
                         return_data=False,
                         fig_size=(8, 8),
                         font_size=14,
                         grid=True):
        """
        Create mean light curve by Collapse the 2D fits image along time axis.
        Eithers saves the image or returns the data

        Input arguments:
            plot (Boolean): plot it or not, Default True
            out_image(string): name of the image to be saved
            return_data (Boolean):  return data or not (default False)

        returns:if return_data is set to True
                list of collapsed 1d array (1d numpy array),
                 respective time in sec of a day(1d numpy array),
                 respective time in datetime.datetime object(1d list)
        """
        # open input fits file
        hdus = self.hdus
        image_hdu = hdus[0]
        image_header = image_hdu.header
        image_data = image_hdu.data
        bin_table_hdu = hdus[1]
        # bintbl_freq_data = bin_table_hdu.data[0][1]

        # Sum the data along oth axis
        sum_image = np.sum(image_data, axis=0)
        sum_image = sum_image / image_data.shape[
            0]  # divide by 200 to normalize

        start_date = utils.to_date(image_header['DATE-OBS'])
        start_time = utils.to_time(image_header['TIME-OBS'])
        start_time = dt.datetime.combine(start_date,
                                         start_time)  # make a datetime object
        end_time = utils.to_time(image_header['TIME-END'])
        end_time = dt.datetime.combine(start_date, end_time)
        time_delta = dt.timedelta(days=0,
                                  hours=0,
                                  minutes=0,
                                  seconds=image_header['CDELT1'])

        def get_time_axis(start, end, delta):
            curr = start
            while curr < end:
                yield curr
                curr += delta

        time_axis = [
            time for time in get_time_axis(start_time, end_time, time_delta)
        ]

        if plot:
            fig, ax = plt.subplots(figsize=(fig_size[0], fig_size[1]))
            ax.plot_date(time_axis, sum_image, 'b-', xdate=True)
            ax.xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
            plt.xticks(rotation=45)
            plt.xlabel('Universal Time', fontSize=font_size)
            plt.ylabel('Total count', fontSize=font_size)
            # title = infits + "\n" + image_header['DATE-OBS'] + "::" + image_header['TIME-OBS']
            # title = self.image_header['CONTENT']

            plt.title("Mean light curve", fontSize=font_size)
            if grid:
                plt.grid()
            plt.savefig(out_image)

        else:
            if return_data:
                # generate numpy array of sec. of a day
                x_start = int(image_header['CRVAL1'])
                x_step = float(image_header['CDELT1'])
                x_length = int(image_header['NAXIS1'])
                x_end = x_start + (x_step * x_length)
                time_in_sec = np.arange(x_start, x_end, x_step)

                # compose data into a list
                data = [sum_image, time_in_sec, time_axis]
                # hdus.close()
                return data
Esempio n. 5
0
    def spectrogram(self,
                    option=3,
                    xtick=2,
                    blevel=0,
                    end_pts=[False, False],
                    fig_size=(8, 6),
                    cmap=cm.jet,
                    color_bar=True,
                    color_bar_ori='vertical',
                    font_size=14):
        """
        Return a matplotlib.pyplot.plot object representing the plot of the input fits file.
        input arguments:
            xticks: frequency of xticks in mins (default =2 )
            blevel: background level (default = 0)
            figsize: a tuple representing size of image (default = (8,6))
            cmap: a matplotlib colormap object (default = cm.jet)
            cbar: to plot a colorbar or not (default = true)
            color_bar_ori: colorbar orientation (default = 'vertical')
            font_size: font_size used in plot (default = 14)

        """

        fig, ax = plt.subplots(figsize=(fig_size[0], fig_size[1]))

        if option == 1:
            y, x = self.imageHdu.data.shape
            cax = ax.imshow(self.imageHdu.data,
                            extent=[0, x, 0, y],
                            aspect='auto',
                            cmap=cmap,
                            vmin=blevel)
            if color_bar:
                ticks = list(
                    np.linspace(
                        blevel, self.dataMax,
                        10).astype('int'))  # calculate 10 ticks positions
                if color_bar_ori == 'horizontal':
                    color_bar = fig.colorbar(cax,
                                             ticks=ticks,
                                             orientation='horizontal')
                else:
                    color_bar = fig.colorbar(cax, ticks=ticks)
                color_bar.set_label('Intensity', rotation=90)

            plt.xlabel('Row Count')
            plt.ylabel('Column Count')

        if option == 2:
            x_start = int(self.imageHeader['CRVAL1'])
            x_step = float(self.imageHeader['CDELT1'])
            x_length = int(self.imageHeader['NAXIS1'])
            x_end = x_start + x_step * x_length
            freqs = self.binTableHdu.data['frequency'][
                0]  # these are true frequencies
            cax = ax.imshow(self.imageHdu.data,
                            extent=[x_start, x_end, freqs[-1], freqs[0]],
                            aspect='auto',
                            cmap=cmap,
                            vmin=blevel)

            if color_bar:
                ticks = list(
                    np.linspace(
                        blevel, self.dataMax,
                        10).astype('int'))  # calculate 10 ticks positins
                if color_bar_ori == 'horizontal':
                    color_bar = fig.colorbar(cax,
                                             ticks=ticks,
                                             orientation='horizontal')
                else:
                    color_bar = fig.colorbar(cax, ticks=ticks)
                color_bar.set_label('Intensity', rotation=90)

            if end_pts[1]:
                # set y minorticks for first and last frequency
                y_lims = [freqs[-1], freqs[0]]
                plt.yticks(list(plt.yticks()[0]) + y_lims)

            plt.xlabel('Time (sec of day)')
            plt.ylabel('Frequency (MHz)')

        if option == 3:
            # get the start time and end time of observation
            start_date = utils.to_date(self.imageHeader['DATE-OBS'])
            start_time = utils.to_time(self.imageHeader['TIME-OBS'])

            start_time = dt.datetime.combine(
                start_date, start_time)  # make a datetime object
            end_time = utils.to_time(self.imageHeader['TIME-END'])
            end_time = dt.datetime.combine(start_date, end_time)

            # get the frequencies
            freqs = self.binTableHdu.data['frequency'][
                0]  # these are true frequencies

            # set the limits for plotting
            x_lims = [start_time, end_time]
            x_lims = mdates.date2num(x_lims)  # dates to numeric values
            y_lims = [freqs[-1], freqs[0]]

            cax = ax.imshow(
                self.imageHdu.data,
                extent=[x_lims[0], x_lims[1], y_lims[0], y_lims[1]],
                aspect='auto',
                cmap=cmap,
                vmin=blevel)
            if color_bar:
                ticks = list(
                    np.linspace(
                        blevel, self.dataMax,
                        10).astype('int'))  # calculate 10 ticks positions
                if color_bar_ori == 'horizontal':
                    color_bar = fig.colorbar(cax,
                                             ticks=ticks,
                                             orientation='horizontal')
                else:
                    color_bar = fig.colorbar(cax, ticks=ticks)
                color_bar.set_label('Intensity', rotation=90)

            ax.xaxis_date()  # x axis has a date data

            ax.xaxis.set_major_locator(
                mdates.MinuteLocator(byminute=range(60),
                                     interval=xtick,
                                     tz=None))
            ax.xaxis.set_major_formatter(DateFormatter('%H:%M:%S'))

            # set ytick labels to be integers only, in case we have a small frequency range, pyplot tends to show
            # fraction
            ax.get_yaxis().get_major_formatter().set_useOffset(False)

            if end_pts[0]:
                # get the start time and end time ans set ticks at those positions on x-axis using minor_locator
                total_sec = utils.tosec(end_time - start_time)
                ax.xaxis.set_minor_locator(
                    mdates.SecondLocator(bysecond=None,
                                         interval=total_sec,
                                         tz=None))
                ax.xaxis.set_minor_formatter(DateFormatter('%H:%M:%S'))
            fig.autofmt_xdate()

            if end_pts[1]:
                # set y minorticks for first and last frequency
                plt.yticks(list(plt.yticks()[0]) + y_lims)

            # ax.xaxis.set_minor_formatter(DateFormatter('%H:%M:%S'))
            plt.xlabel('Universal Time')
            plt.ylabel('Frequency (MHz)')

        title = self.imageHeader['CONTENT']
        plt.title(title)
        return plt
Esempio n. 6
0
    def slice_time_axis(self, time1, time2):
        """
        Make a slice of input radiohelliograph observation fits file along a time axis and return a new object

        input arguments:
            time1 (string): start of a slice, time in HH:MM:SSformat
            time2 (string): end of a slice, time in HH:MM:SS format

        Returns
            PyCallisto object
        """

        # assuming that the input file has same start date and end date  (i.e. observed on the same day)
        # time1 and time 2 is in HH:MM:SS
        if not (len(time1.split(':')) == 3):
            raise Exception(
                "Time format not proper, please provide time in HH:MM:SS format"
            )

        if not (len(time2.split(':')) == 3):
            raise Exception(
                "Time format not proper, please provide time in HH:MM:SS format"
            )

        # check the dates
        start_date = utils.to_date(self.imageHeader['DATE-OBS'])
        end_date = utils.to_date(self.imageHeader['DATE-END'])
        if not start_date == end_date:
            raise Exception(
                "start_date and end date differ, right now we do not support this"
            )

        # get the times in datetime.date format for easy manipulation
        start_time = utils.to_time(
            self.imageHeader['TIME-OBS'])  # datetime.date object
        start_time = dt.datetime.combine(
            start_date, start_time)  # datetime.datetime object
        end_time = utils.to_time(self.imageHeader['TIME-END'])
        end_time = dt.datetime.combine(start_date, end_time)

        time1 = utils.to_time(time1)
        time1 = dt.datetime.combine(start_date, time1)
        time2 = utils.to_time(time2)
        time2 = dt.datetime.combine(start_date, time2)

        # check the "time constraints"
        if not (time1 < time2):
            time1, time2 = time2, time1
        if not (start_time < time1):
            # print("Time1 out of bound, can't slice!")
            print("Start time of input file : ", start_time)
            print("End time of input file : ", end_time)
            raise Exception("Time1 out of bound, can't slice!")

        if not (end_time > time2):
            # print("Time2 out of bound, can't slice!")
            print("Start time of input file : ", start_time)
            print("End time of input file : ", end_time)
            raise Exception("Time2 out of bound, can't slice!")

        # get the start_pixel and end_pixel in piselterms from input of time1 and time2
        start_pixel = time1 - start_time
        start_pixel = utils.tosec(start_pixel)  # in seconds
        start_offset = start_pixel
        start_pixel = int(start_pixel / float(self.imageHeader['CDELT1']))

        end_pixel = time2 - start_time
        end_pixel = utils.tosec(end_pixel)
        end_pixel = int(end_pixel / float(self.imageHeader['CDELT1']))

        # do the actual slicing
        image_data = copy.deepcopy(self.imageHdu.data)
        image_data = image_data[:, start_pixel:end_pixel]

        # update the image_header accordingly
        image_header = copy.deepcopy(self.imageHeader)
        image_header['NAXIS1'] = image_data.shape[1]
        image_header['TIME-OBS'] = str(time1.time())
        image_header['TIME-END'] = str(time2.time())
        image_header['DATAMIN'] = image_data.min()
        image_header['DATAMAX'] = image_data.max()
        image_header['CRVAL1'] = int(self.imageHeader['CRVAL1']) + start_offset

        # create a primary hdu containing this image and header data
        image_hdu = pyfits.PrimaryHDU(image_data, header=image_header)
        new_hdu_list = pyfits.HDUList([image_hdu])

        # create a new bintable and update it in data structure
        x_length = end_pixel - start_pixel
        range_list = [x * 1.0 for x in range(x_length)]
        bin_table_data_time = np.array([range_list])
        bin_table_data_freqs = list(self.binTableHdu.data[0][1].copy())
        bin_table_data_freqs = np.array([bin_table_data_freqs])

        format1 = str(bin_table_data_time.shape[1]) + "D8.3"
        format2 = str(bin_table_data_freqs.shape[1]) + "D8.3"
        col1 = pyfits.Column(name='TIME',
                             format=format1,
                             array=bin_table_data_time)
        col2 = pyfits.Column(name='FREQUENCY',
                             format=format2,
                             array=bin_table_data_freqs)
        cols = pyfits.ColDefs(np.asarray([col1, col2]))
        tb_hdu = pyfits.BinTableHDU.from_columns(cols)

        # add it to new hdulist we have created
        new_hdu_list.append(tb_hdu)

        return PyCallisto(new_hdu_list)
Esempio n. 7
0
    def append_time_axis(self, fits2):
        """
        Take second radiohelliograph observation fits file and join two in time axis (x axis) and return new
        PyCallisto object.


        input arguments:
            fits2: path of a Second input fits file or PyCallisto object

        """

        # get image_data of first fits file
        image_data1 = self.imageHdu.data

        # get the image data of second fits file
        # (which is the argument here, could be a string/path of fits file or PyCallisto object)

        # if argument is a string (representing path of fits file)
        if isinstance(fits2, str):
            # check if it is proper callisto file or not
            if not (utils.check_fits_callisto(fits2)):
                raise Exception("Fits file is not proper callisto files")

            # get the data
            hdus = pyfits.open(fits2)
            image_hdu2 = hdus[0]
            bin_table_hdu2 = hdus[1]
            image_header2 = image_hdu2.header
            bin_header2 = bin_table_hdu2.header
            image_data2 = image_hdu2.data

        else:  # if argument is a PyCallisto object

            image_hdu2 = fits2.hdus[0]
            bin_table_hdu2 = fits2.hdus[1]
            image_header2 = image_hdu2.header
            bin_header2 = bin_table_hdu2.header
            image_data2 = image_hdu2.data

        # check if both imagedats they have same y dimensions (frequency in out case)
        if not image_data1.shape[0] == image_data2.shape[0]:
            raise Exception(
                "Frequency dimensions do not match, cannot concatinate files")

        # check the order of fits files in time axis, if not correct, flip it

        # get start time of first file
        start_date = utils.to_date(self.imageHeader['DATE-OBS'])
        start_time = utils.to_time(self.imageHeader['TIME-OBS'])
        start_time1 = dt.datetime.combine(start_date,
                                          start_time)  # make a datetime object

        # get start time of second
        start_date = utils.to_date(image_header2['DATE-OBS'])
        start_time = utils.to_time(image_header2['TIME-OBS'])
        start_time2 = dt.datetime.combine(start_date,
                                          start_time)  # make a datetime object

        # if input files in not proper  order in time swap them
        if not start_time1 < start_time2:
            image_hdu2, bin_table_hdu2, image_header2, bin_header2, image_data2, self.imageHdu,  = \
                self.imageHdu, self.binTableHdu, self.imageHeader, self.binheader, image_data1, image_hdu2,

            self.binTableHdu, self.imageHeader, self.binheader, image_data1 = \
                image_header2, bin_header2, image_data2, bin_table_hdu2

            start_time1, start_time2 = start_time2, start_time1

        # end_time of first file
        end_date = utils.to_date(self.imageHeader['DATE-END'])
        end_time = utils.to_time(self.imageHeader['TIME-END'])
        end_time1 = dt.datetime.combine(end_date,
                                        end_time)  # make a datetime object

        # check that two fits files are continuous in time axis
        td_sec = dt.timedelta(seconds=1)
        if start_time2 - end_time1 > td_sec:
            raise Exception(
                "Fits  files are not continuous in time axis, cannot join them"
            )

        # check if both the files have same sampling /
        if not self.imageHeader['CDELT1'] == image_header2['CDELT1']:
            raise Exception(
                "Two fits files do not have the same sampling in time axis, cannot join them"
            )

        # join the numpy Array
        image_data = np.concatenate((image_data1, image_data2), axis=1)

        # compose a new image header
        image_header = copy.deepcopy(self.imageHeader)
        image_header['NAXIS1'] = image_data.shape[1]
        image_header['DATE-END'] = image_header2['DATE-END']
        image_header['TIME-END'] = image_header2['TIME-END']
        image_header['DATAMIN'] = image_data.min()
        image_header['DATAMAX'] = image_data.max()
        image_header['COMMENT'] = "created on " + str(dt.datetime.now(
        )) + " by joining fits files "  # + str(self.infits) + " " + str(fits2)

        # create a primary hdu containing this image and header data
        image_hdu = pyfits.PrimaryHDU(image_data, header=image_header)
        new_hdulist = pyfits.HDUList([image_hdu])

        # bintabledata
        x_length = int(self.imageHeader['NAXIS1']) + int(
            image_header2['NAXIS1'])
        x_length = int(x_length)

        range_list = [x * 1.0 for x in range(x_length)]
        bin_table_data_time = np.array([range_list])
        bintable_data_freqs = list(self.binTableHdu.data[0][1].copy())
        bintable_data_freqs = np.array([bintable_data_freqs])

        # these two arrays needs to be two dimensional, though the content is one dimensional,
        # to be in sync with original data format, which is 1RX2C

        # generalize the "format"
        format1 = str(bin_table_data_time.shape[1]) + "D8.3"
        format2 = str(bintable_data_freqs.shape[1]) + "D8.3"
        col1 = pyfits.Column(name='TIME',
                             format=format1,
                             array=bin_table_data_time)
        col2 = pyfits.Column(name='FREQUENCY',
                             format=format2,
                             array=bintable_data_freqs)
        cols = pyfits.ColDefs(np.asarray([col1, col2]))

        # create bintable and  add it to hdulist
        tbhdu = pyfits.BinTableHDU.from_columns(cols)
        new_hdulist.append(tbhdu)

        # return new pycallisto object
        return PyCallisto(new_hdulist)