fits.py 7.83 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
ephem    
Wei Shoulin committed
15
from csst_dfs_commons.models import Result
Wei Shoulin's avatar
Wei Shoulin committed
16
17
18

log = logging.getLogger('csst')
class FitsApi(object):
Wei Shoulin's avatar
Wei Shoulin committed
19
20
    def __init__(self, sub_system = "ifs"):
        self.sub_system = sub_system
Wei Shoulin's avatar
Wei Shoulin committed
21
22
23
24
25
26
27
28
        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
29
30
        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
31
32
33
34

    def find(self, **kwargs):
        '''
        parameter kwargs:
Wei Shoulin's avatar
Wei Shoulin committed
35
36
37
38
39
            obs_time = [int],
            file_name = [str],
            exp_time = (start, end),
            ccd_num = [int],
            qc0_status = [int],
Wei Shoulin's avatar
ephem    
Wei Shoulin committed
40
41
            prc_status = [int],
            limit: limits returns the number of records
Wei Shoulin's avatar
Wei Shoulin committed
42

Wei Shoulin's avatar
ephem    
Wei Shoulin committed
43
        return: csst_dfs_common.models.Result
Wei Shoulin's avatar
Wei Shoulin committed
44
        '''
Xie Zhou's avatar
update    
Xie Zhou committed
45
        paths = []
Xie Zhou's avatar
Xie Zhou committed
46
        
Xie Zhou's avatar
update    
Xie Zhou committed
47
        obs_time = get_parameter(kwargs, "obs_time")
Wei Shoulin's avatar
Wei Shoulin committed
48
49
50
51
52
        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")
Wei Shoulin's avatar
ephem    
Wei Shoulin committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
        limit = get_parameter(kwargs, "limit", 0)
        limit = to_int(limit, 0)

        try:
            
            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=" + repr(obs_time))
            if ccd_num is not None:
                sql.append(" and ccd_num=" + repr(ccd_num))
            if qc0_status is not None:
                sql.append(" and qc0_status=" + repr(qc0_status)) 
            if prc_status is not None:
                sql.append(" and prc_status=" + repr(prc_status))
            if limit > 0:
                sql.append(f" limit {limit}")
            
            if file_name:
                sql = ["select * from ifs_rawfits where filename='" + file_name + "'"]

            totalCount = self.db.select_one("".join(sql).replace("select * from","select count(*) as v from"))

            _, recs = self.db.select_many("".join(sql))
            for r in recs:
                r['file_path'] = os.path.join(self.root_dir, r['file_path'])

            return Result.ok_data(data=recs).append("totalCount", totalCount['v'])
        except Exception as e:
            return Result.error(message=e.message)
Wei Shoulin's avatar
Wei Shoulin committed
87
88
89
90
91
92
93
94

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

        return dict or None
        '''
Wei Shoulin's avatar
ephem    
Wei Shoulin committed
95
96
97
98
99
100
101
102
103
        try:
            fits_id = get_parameter(kwargs, "fits_id", -1)
            r = self.db.select_one(
                "select * from ifs_rawfits where id=?", (fits_id,))
            if r:
                r['file_path'] = os.path.join(self.root_dir, r['file_path'])
            return Result.ok_data(data=r)
        except Exception as e:
            return Result.error(message=e.message)
Wei Shoulin's avatar
Wei Shoulin committed
104
105
106
107

    def read(self, **kwargs):
        '''
        parameter kwargs:
Wei Shoulin's avatar
Wei Shoulin committed
108
109
110
            fits_id = [int],
            file_path = [str], 
            chunk_size = [int] default 20480
Xie Zhou's avatar
update    
Xie Zhou committed
111

Wei Shoulin's avatar
Wei Shoulin committed
112
113
114
115
116
117
118
119
120
        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
121
122
123
            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
124
                file_path = r["file_path"]
Wei Shoulin's avatar
Wei Shoulin committed
125
126

        if file_path is not None:
Wei Shoulin's avatar
Wei Shoulin committed
127
128
            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
129

Wei Shoulin's avatar
Wei Shoulin committed
130
131
132
    def update_proc_status(self, **kwargs):
        '''
        parameter kwargs:
Wei Shoulin's avatar
Wei Shoulin committed
133
134
            fits_id = [int],
            status = [int]
Wei Shoulin's avatar
Wei Shoulin committed
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
        '''
        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
151

Wei Shoulin's avatar
Wei Shoulin committed
152
    def update_qc0_status(self, **kwargs):
Xie Zhou's avatar
update    
Xie Zhou committed
153
154
        '''
        parameter kwargs:
Wei Shoulin's avatar
Wei Shoulin committed
155
156
            fits_id = [int],
            status = [int]
Wei Shoulin's avatar
Wei Shoulin committed
157
        '''
Xie Zhou's avatar
update    
Xie Zhou committed
158

Wei Shoulin's avatar
Wei Shoulin committed
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
        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
177
        reduce the header of fits file of server and insert a record into database
Wei Shoulin's avatar
Wei Shoulin committed
178
179
        parameter kwargs:
            file_path = [str]
Xie Zhou's avatar
update    
Xie Zhou committed
180
181
182
183
184
        '''
        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
185
186
187
188
189
        
        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
190

Wei Shoulin's avatar
Wei Shoulin committed
191
192
193
194
195
        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
196
        )
Wei Shoulin's avatar
Wei Shoulin committed
197
198
        if existed:
            log.warning('%s has already been imported' %(file_path, ))
Xie Zhou's avatar
update    
Xie Zhou committed
199
200
            return

Wei Shoulin's avatar
Wei Shoulin committed
201
202
        hu = fits.getheader(file_full_path)
        obs_time = hu['obst'] if 'obst' in hu else '1'
Xie Zhou's avatar
Xie Zhou committed
203
        ccd_num = hu['ccd_num'] if 'ccd_num' in hu else 0
Wei Shoulin's avatar
Wei Shoulin committed
204
        exp_time = format_time_ms(time.time())
Xie Zhou's avatar
update    
Xie Zhou committed
205
206

        self.db.execute(
Wei Shoulin's avatar
Wei Shoulin committed
207
208
209
            '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
210
        )
Wei Shoulin's avatar
Wei Shoulin committed
211
212
213
214
215
        self.db.end()

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

    def write(self, **kwargs):
Wei Shoulin's avatar
Wei Shoulin committed
216
217
218
219
220
        '''
        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
221
222
223
224
225
226
227
228
        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
229
                "/".join([str(datetime.now().year),"%02d"%(datetime.now().month),"%02d"%(datetime.now().day)]))
Wei Shoulin's avatar
Wei Shoulin committed
230
231
232
233
234

        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
235
236
237
238
239
        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)