fits.py 7.07 KB
Newer Older
Wei Shoulin's avatar
Wei Shoulin committed
1
2

import logging
Xie Zhou's avatar
update    
Xie Zhou committed
3
import os
Wei Shoulin's avatar
Wei Shoulin committed
4
from os.path import join
Xie Zhou's avatar
update    
Xie Zhou committed
5
import shutil
Wei Shoulin's avatar
Wei Shoulin committed
6
7
8
import time, datetime
import shutil

Xie Zhou's avatar
update    
Xie Zhou committed
9
10
11
12
from glob import glob

from astropy.io import fits

Wei Shoulin's avatar
Wei Shoulin committed
13
from ..common.db import DBClient
Wei Shoulin's avatar
Wei Shoulin committed
14
from ..common.utils import *
Wei Shoulin's avatar
Wei Shoulin committed
15
16
17

log = logging.getLogger('csst')
class FitsApi(object):
Wei Shoulin's avatar
Wei Shoulin committed
18
19
    def __init__(self, sub_system = "ifs"):
        self.sub_system = sub_system
Wei Shoulin's avatar
Wei Shoulin committed
20
21
22
23
24
25
26
27
        self.root_dir = os.getenv("CSST_LOCAL_FILE_ROOT", "/opt/temp/csst")
        self.check_dir()
        self.db = DBClient()

    def check_dir(self):
        if not os.path.exists(self.root_dir):
            os.mkdir(self.root_dir)
            log.info("using [%s] as root directory", self.root_dir)
Wei Shoulin's avatar
Wei Shoulin committed
28
29
        if not os.path.exists(os.path.join(self.root_dir, "fits")):
            os.mkdir(os.path.join(self.root_dir, "fits"))
Wei Shoulin's avatar
Wei Shoulin committed
30
31
32
33

    def find(self, **kwargs):
        '''
        parameter kwargs:
Wei Shoulin's avatar
Wei Shoulin committed
34
35
36
37
38
            obs_time = [int],
            file_name = [str],
            exp_time = (start, end),
            ccd_num = [int],
            qc0_status = [int],
Wei Shoulin's avatar
Wei Shoulin committed
39
            prc_status = [int]
Wei Shoulin's avatar
Wei Shoulin committed
40

Wei Shoulin's avatar
Wei Shoulin committed
41
        return list of raw records
Wei Shoulin's avatar
Wei Shoulin committed
42
        '''
Xie Zhou's avatar
update    
Xie Zhou committed
43
        paths = []
Xie Zhou's avatar
Xie Zhou committed
44
        
Xie Zhou's avatar
update    
Xie Zhou committed
45
        obs_time = get_parameter(kwargs, "obs_time")
Wei Shoulin's avatar
Wei Shoulin committed
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
        file_name = get_parameter(kwargs, "file_name")
        exp_time = get_parameter(kwargs, "exp_time", (None, format_time_ms(time.time())))
        ccd_num = get_parameter(kwargs, "ccd_num")
        qc0_status = get_parameter(kwargs, "qc0_status")
        prc_status = get_parameter(kwargs, "prc_status")
        
        sql = []

        sql.append("select * from ifs_rawfits where exp_time<='" + exp_time[1]+"'")

        if exp_time[0] is not None:
            sql.append(" and exp_time>='" + exp_time[0] + "'")
        if obs_time is not None:
            sql.append(" and obs_time=" + obs_time)
        if ccd_num is not None:
            sql.append(" and ccd_num=" + ccd_num)
        if qc0_status is not None:
            sql.append(" and qc0_status=" + qc0_status) 
        if prc_status is not None:
            sql.append(" and prc_status=" + prc_status)
        
        if file_name:
            sql = ["select * from ifs_rawfits where filename='" + file_name + "'"]
Wei Shoulin's avatar
Wei Shoulin committed
69
70
71
72
        _, recs = self.db.select_many("".join(sql))
        for r in recs:
            r['file_path'] = os.path.join(self.root_dir, r['file_path'])
        return recs
Wei Shoulin's avatar
Wei Shoulin committed
73
74
75
76
77
78
79
80
81
82
83

    def get(self, **kwargs):
        '''
        parameter kwargs:
            fits_id = [int] 

        return dict or None
        '''
        fits_id = get_parameter(kwargs, "fits_id", -1)
        r = self.db.select_one(
            "select * from ifs_rawfits where id=?", (fits_id,))
Wei Shoulin's avatar
Wei Shoulin committed
84
85
        if r:
            r['file_path'] = os.path.join(self.root_dir, r['file_path'])
Wei Shoulin's avatar
Wei Shoulin committed
86
        return r
Wei Shoulin's avatar
Wei Shoulin committed
87
88
89
90

    def read(self, **kwargs):
        '''
        parameter kwargs:
Wei Shoulin's avatar
Wei Shoulin committed
91
92
93
            fits_id = [int],
            file_path = [str], 
            chunk_size = [int] default 20480
Xie Zhou's avatar
update    
Xie Zhou committed
94

Wei Shoulin's avatar
Wei Shoulin committed
95
96
97
98
99
100
101
102
103
        yield bytes of fits file
        '''
        fits_id = get_parameter(kwargs, "fits_id")
        file_path = get_parameter(kwargs, "file_path")

        if fits_id is None and file_path is None:
            raise Exception("fits_id or file_path need to be defined")

        if fits_id is not None:
Wei Shoulin's avatar
Wei Shoulin committed
104
105
106
            r = self.db.select_one(
                "select * from ifs_rawfits where id=?", (fits_id,))
            if r is not None:
Wei Shoulin's avatar
Wei Shoulin committed
107
                file_path = r["file_path"]
Wei Shoulin's avatar
Wei Shoulin committed
108
109

        if file_path is not None:
Wei Shoulin's avatar
Wei Shoulin committed
110
111
            chunk_size = get_parameter(kwargs, "chunk_size", 20480)
            return yield_file_bytes(os.path.join(self.root_dir, file_path), chunk_size)
Wei Shoulin's avatar
Wei Shoulin committed
112

Wei Shoulin's avatar
Wei Shoulin committed
113
114
115
    def update_proc_status(self, **kwargs):
        '''
        parameter kwargs:
Wei Shoulin's avatar
Wei Shoulin committed
116
117
            fits_id = [int],
            status = [int]
Wei Shoulin's avatar
Wei Shoulin committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
        '''
        fits_id = get_parameter(kwargs, "fits_id")
        status = get_parameter(kwargs, "status")

        existed = self.db.exists(
            "select * from ifs_rawfits where id=?",
            (fits_id,)
        )
        if not existed:
            log.warning('%s not found' %(fits_id, ))
            return
        self.db.execute(
            'update ifs_rawfits set prc_status=?, prc_time=? where id=?',
            (status, format_time_ms(time.time()), fits_id)
        )  
        self.db.end() 
Wei Shoulin's avatar
Wei Shoulin committed
134

Wei Shoulin's avatar
Wei Shoulin committed
135
    def update_qc0_status(self, **kwargs):
Xie Zhou's avatar
update    
Xie Zhou committed
136
137
        '''
        parameter kwargs:
Wei Shoulin's avatar
Wei Shoulin committed
138
139
            fits_id = [int],
            status = [int]
Wei Shoulin's avatar
Wei Shoulin committed
140
        '''
Xie Zhou's avatar
update    
Xie Zhou committed
141

Wei Shoulin's avatar
Wei Shoulin committed
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
        fits_id = get_parameter(kwargs, "fits_id")
        status = get_parameter(kwargs, "status")

        existed = self.db.exists(
            "select * from ifs_rawfits where id=?",
            (fits_id,)
        )
        if not existed:
            log.warning('%s not found' %(fits_id, ))
            return
        self.db.execute(
            'update ifs_rawfits set qc0_status=?, qc0_time=? where id=?',
            (status, format_time_ms(time.time()), fits_id)
        )  
        self.db.end() 

    def import2db(self, **kwargs):
        '''
Wei Shoulin's avatar
Wei Shoulin committed
160
        reduce the header of fits file of server and insert a record into database
Wei Shoulin's avatar
Wei Shoulin committed
161
162
        parameter kwargs:
            file_path = [str]
Xie Zhou's avatar
update    
Xie Zhou committed
163
164
165
166
167
        '''
        file_path = get_parameter(kwargs, "file_path")

        if file_path is None:
            raise Exception("file_path need to be defined")
Wei Shoulin's avatar
Wei Shoulin committed
168
169
170
171
172
        
        file_full_path = os.path.join(self.root_dir, file_path)

        if not os.path.exists(file_full_path):
            raise Exception("%s not found" % (file_full_path))
Xie Zhou's avatar
update    
Xie Zhou committed
173

Wei Shoulin's avatar
Wei Shoulin committed
174
175
176
177
178
        file_name = os.path.basename(file_path)

        existed = self.db.exists(
            "select * from ifs_rawfits where filename=?",
            (file_name,)
Xie Zhou's avatar
update    
Xie Zhou committed
179
        )
Wei Shoulin's avatar
Wei Shoulin committed
180
181
        if existed:
            log.warning('%s has already been imported' %(file_path, ))
Xie Zhou's avatar
update    
Xie Zhou committed
182
183
            return

Wei Shoulin's avatar
Wei Shoulin committed
184
185
        hu = fits.getheader(file_full_path)
        obs_time = hu['obst'] if 'obst' in hu else '1'
Xie Zhou's avatar
Xie Zhou committed
186
        ccd_num = hu['ccd_num'] if 'ccd_num' in hu else 0
Wei Shoulin's avatar
Wei Shoulin committed
187
        exp_time = format_time_ms(time.time())
Xie Zhou's avatar
update    
Xie Zhou committed
188
189

        self.db.execute(
Wei Shoulin's avatar
Wei Shoulin committed
190
191
192
            'INSERT INTO ifs_rawfits (filename, obs_time, ccd_num, exp_time, file_path, qc0_status, prc_status, create_time) \
                VALUES (?,?,?,?,?,?,?,?)',
            (file_name, obs_time, ccd_num, exp_time, file_path, 0,  0, format_time_ms(time.time()),)
Xie Zhou's avatar
update    
Xie Zhou committed
193
        )
Wei Shoulin's avatar
Wei Shoulin committed
194
195
196
197
198
        self.db.end()

        log.info("raw fits %s imported.", file_path)

    def write(self, **kwargs):
Wei Shoulin's avatar
Wei Shoulin committed
199
200
201
202
203
        '''
        copy a local file to file storage, then reduce the header of fits file and insert a record into database
        parameter kwargs:
            file_path = [str]
        '''        
Wei Shoulin's avatar
Wei Shoulin committed
204
205
206
207
208
209
210
211
        file_path = get_parameter(kwargs, "file_path")

        if not file_path:
            log.error("file_path is None")
            return

        new_file_dir = create_dir(os.path.join(self.root_dir, "fits"),
                self.sub_system, 
Wei Shoulin's avatar
Wei Shoulin committed
212
                "/".join([str(datetime.now().year),"%02d"%(datetime.now().month),"%02d"%(datetime.now().day)]))
Wei Shoulin's avatar
Wei Shoulin committed
213
214
215
216
217

        file_basename = os.path.basename(file_path)
        new_file_path = os.path.join(new_file_dir, file_basename)
        shutil.copyfile(file_path, new_file_path)

Wei Shoulin's avatar
Wei Shoulin committed
218
219
220
221
222
        file_path = new_file_path.replace(self.root_dir, '')
        if file_path.index("/") == 0:
            file_path = file_path[1:]

        self.import2db(file_path = file_path)