class User(BaseModel): id = peewee.PrimaryKeyField() name = peewee.TextField(null=True) banned = peewee.BooleanField(default=False) last_activity = peewee.DateTimeField(null=True) superuser = peewee.BooleanField(default=False)
class Compet(BaseModel): user1 = peewee.CharField() user2 = peewee.CharField() game = peewee.ForeignKeyField(Game) game_date = peewee.DateTimeField() winner = peewee.IntegerField(default=0)
class Organization(DomainObject): '''Organization. Доменный класс. \n name: TextField - поле, хранит название организации - сайта\n creation_date: DateTimeField - поле, хранит дату создания организации''' name = peewee.TextField() creation_date = peewee.DateTimeField(default=datetime.datetime.utcnow)
class PlaceBook(base.BaseModel): place = peewee.ForeignKeyField(place.Place) user = peewee.ForeignKeyField(user.User, related_name="places_booked") is_validated = peewee.BooleanField(default=False) date_start = peewee.DateTimeField(null=False) number_nights = peewee.IntegerField(default=1)
class BaseModel(db.Model): """Automatically keep the model's creation time.""" created = pw.DateTimeField(default=dt.datetime.utcnow)
class DriveArchive(BaseModel): drive_id = peewee.CharField(unique=True) date_modified_on_disk = peewee.DateTimeField() md5sum = peewee.CharField(null=True)
class Entry(peewee.Model): uid = peewee.TextField(primary_key=True) title = peewee.TextField() contents = peewee.TextField() timestamp = peewee.DateTimeField(index=True) extra = peewee.TextField()
def migrate(migrator, database, fake=False, **kwargs): """Write your migrations here.""" migrator.add_fields('sensordangermessage', created_at=pw.DateTimeField(default=dt.datetime.now))
class ContatoModel(BaseDBModel): retorno = peewee.CharField() texto = peewee.TextField() user = peewee.TextField() created_at = peewee.DateTimeField(default=datetime.now)
class DbBanned(BaseModel): ip = peewee.ForeignKeyField(DbIp, backref="bans") date = peewee.DateTimeField() duration = peewee.IntegerField()
class Feed(peewee.Model): name = peewee.CharField() url = peewee.CharField(max_length=200) last_status = peewee.CharField(null=True) etag = peewee.CharField(max_length=200) last_modified = peewee.DateTimeField()
class DbValidAccount(BaseModel): date_added = peewee.DateTimeField(default=datetime.datetime.now) date_last_check = peewee.DateTimeField(default=datetime.datetime.now) ip = peewee.ForeignKeyField(DbIp, backref="accounts") username = peewee.ForeignKeyField(DbUsername, backref="accounts") password = peewee.ForeignKeyField(DbPassword, backref="accounts")
class DbLog(BaseModel): ip = peewee.ForeignKeyField(DbIp, backref="logs") username = peewee.ForeignKeyField(DbUsername, backref="logs") password = peewee.ForeignKeyField(DbPassword, backref="logs") date = peewee.DateTimeField(default=datetime.datetime.now)
class Request(BaseModel): user = peewee.ForeignKeyField(User) text = peewee.CharField() time = peewee.DateTimeField(default=datetime.datetime.now)
class Message(db.Model): block_hash = peewee.CharField(max_length=64, index=True) address = peewee.CharField(max_length=64) message_in_raw = peewee.CharField() created_at = peewee.DateTimeField(default=datetime.datetime.utcnow(), index=True) premium = peewee.BooleanField(default=False) hidden = peewee.BooleanField(default=False, index=True) destination = peewee.CharField(max_length=64) class Meta: db_table = 'messages' @staticmethod def validate_block(block : dict) -> tuple: block_contents = json.loads(block['contents']) """Ensure a block is to the appropriate destination, of the minimum amount, etc""" if block_contents['link_as_account'] != AppConfig.MONKEYTALKS_ACCOUNT: return (False, "Transaction wasnt sent to MonkeyTalks account") elif int(block['amount']) - FeeModel.get_fee() <= 0: return (False, "Transaction amount wasn't enough to cover fee") elif not Nanote().validate_message(block['amount']): return (False, "Message has invalid checksum - can't be decoded") return (True, "Valid") @classmethod def save_block_as_message(cls, block : dict): block_contents = json.loads(block['contents']) return cls.save_as_message(block['amount'], block['hash'], block_contents['account'], block_contents['link_as_account']) @classmethod def save_as_message(cls, amount: str, block_hash: str, account: str, destination: str): premium = False if int(amount) - FeeModel().get_premium_fee() > 0: premium = True message = Message( block_hash = block_hash, destination = destination, message_in_raw = str(int(amount)), created_at = datetime.datetime.utcnow(), premium = premium, address = account ) if message.save() > 0: message.inc_message_count() return message return None def inc_message_count(self) -> int: """Increment message count for a particular account and return the new count""" old_count = rd.hget(self.address, RD_COUNT_KEY) if old_count is None: rd.hset(self.address, RD_COUNT_KEY, '1') return 1 else: old_count = int(old_count.decode('utf-8')) old_count += 1 rd.hset(self.address, RD_COUNT_KEY, str(old_count)) return old_count def get_message_count(self) -> int: """Retrieve message count for a particular account""" count = rd.hget(self.address, RD_COUNT_KEY) if count is None: return 0 return int(count.decode('utf-8')) @staticmethod def format_message(message) -> dict: """Format a message in json to send to the UI""" message_json = { 'id': message.id, 'content': message.message_in_raw, 'date': format_js_iso(message.created_at), 'premium': message.premium, 'address': message.address, 'count': message.get_message_count() } return message_json
class RequestTime(BaseModel): ids = peewee.IntegerField(primary_key=True) last_request = peewee.DateTimeField()
class EventMail(BaseModel): id = pw.AutoField(primary_key=True) event = pw.ForeignKeyField(Event, on_delete='CASCADE', on_update='CASCADE') mail = pw.ForeignKeyField(Mail, on_delete='CASCADE', on_update='CASCADE') send_time = pw.DateTimeField() sent = pw.BooleanField(default=False)
class PuppyModel(Model): name = peewee.CharField() number = peewee.IntegerField() time = peewee.DateTimeField() float = peewee.FloatField(null=True) bool = peewee.BooleanField()
class Payment(BaseModel): # status = Pending, Complete, Error student_tutor_session = pw.ForeignKeyField(Student_tutor_session, backref="student_tutor_sessions") amount = pw.DecimalField(null=False) status = pw.CharField(default="pending") status_timestamp = pw.DateTimeField(default=datetime.datetime.now)
class Card(BaseModel): template = pv.ForeignKeyField(Template, backref='cards') note = pv.ForeignKeyField(Note, backref='cards') _front = pv.TextField(unique=True) srs_level = pv.IntegerField(null=True) next_review = pv.DateTimeField(null=True) _decks = pv.ManyToManyField(Deck, backref='cards') last_review = pv.DateTimeField(constraints=[pv.SQL('DEFAULT CURRENT_TIMESTAMP')]) info = sqlite_ext.JSONField(default=dict) backup = None def to_dict(self, max_depth=2, **kwargs): d = super(Card, self).to_dict(manytomany=False, backrefs=False, exclude=['_decks', '_front', 'note'], extra_attrs=['decks', 'front', 'back']) d['note'] = self.note.to_dict() return d @property def decks(self): return [d.name for d in self._decks] @property def front(self): text = self.template.front for k, v in self.note.data.items(): text = text.replace('{{%s}}' % k, str(v)) return text @property def back(self): text = self.template.back if not text: return '\n'.join(' ' * 4 + line for line in json.dumps( self.note.data, indent=2, ensure_ascii=False ).split('\n')) for k, v in self.note.data.items(): text = text.replace('{{%s}}' % k, str(v)) return text def __repr__(self): return self.front @property def data(self): return self.note.data def add_deck(self, deck_name): Deck.get_or_create(name=deck_name)[0].cards.add(self) def remove_deck(self, deck_name): Deck.get_or_create(name=deck_name)[0].cards.remove(self) def mark(self, tag='marked'): return self.note.mark(tag) def unmark(self, tag='marked'): return self.note.unmark(tag) def right(self, step=1): self.undo() if not self.backup: self.backup = model_to_dict(self) print(self.srs_level) if self.srs_level is None: self.srs_level = 0 else: self.srs_level = self.srs_level + step srs = Settings.get().srs try: self.next_review = datetime.now() + srs[self.srs_level] except IndexError: self.next_review = None assert isinstance(self.info, dict) self.info['lapse'] = 0 self.info['streak'] = self.info.get('streak', 0) + 1 self.info['total_right'] = self.info.get('total_right', 0) + 1 self.save() correct = next_srs = right def easy(self, max_srs_level_enabled=3): if self.srs_level < max_srs_level_enabled: return self.right(step=2) else: raise ValueError def wrong(self, next_review=timedelta(minutes=10)): self.undo() if not self.backup: self.backup = model_to_dict(self) if self.srs_level is not None and self.srs_level > 0: self.srs_level = self.srs_level - 1 assert isinstance(self.info, dict) self.info['streak'] = 0 self.info['lapse'] = self.info.get('lapse', 0) + 1 self.info['total_wrong'] = self.info.get('total_wrong', 0) + 1 self.bury(next_review) incorrect = previous_srs = wrong def bury(self, next_review=timedelta(hours=4)): if not self.backup: self.backup = model_to_dict(self) if isinstance(next_review, timedelta): self.next_review = datetime.now() + next_review else: self.next_review = next_review self.save() def reset(self): self.srs_level = None self.next_review = None self.save() def undo(self): if self.backup: dict_to_model(Card, self.backup).save() @classmethod def iter_quiz(cls, **kwargs): db_cards = list(cls.search(**kwargs)) random.shuffle(db_cards) return iter(db_cards) @classmethod def iter_due(cls, **kwargs): return cls.iter_quiz(due=True, **kwargs) @classmethod def search(cls, q_str='', deck=None, tags=None, due=None, offset=0, limit=None): """ :param q_str: :param deck: :param tags: :param bool|None|timedelta|datetime due: :param offset: :param limit: :return: """ query = cls.select() due_is_set = False note_keys = None result = parse_query(q_str) if result: for seg in result: if len(seg) == 1: if note_keys is None: note_keys = set() for srs_note in Note.select(Note.data): note_keys.update(srs_note.data.keys()) note_keys = tuple(note_keys) q_note = Note.data[note_keys[0]].contains(seg[0]) for k in note_keys[1:]: q_note |= Note.data[k].contains(seg[0]) query = query.switch(cls).join(Note).where(q_note) else: if seg[0] == 'due': due_is_set = True if seg[2].lower() == 'true': query = query.switch(cls).where(cls.next_review < datetime.now()) elif seg[2].lower() == 'false': query = query.switch(cls).where(cls.next_review.is_null(True)) else: dur_sec = pytimeparse.parse(seg[2]) if dur_sec: _due = datetime.now() + timedelta(seconds=dur_sec) else: _due = dateutil.parser.parse(seg[2]) query = query.switch(cls).where(cls.next_review < _due) elif seg[0] == 'deck': deck_q = (Deck.name == seg[2]) if seg[1] != '=': deck_q = (deck_q | Deck.name.startswith(seg[2] + '::')) query = query.switch(cls).join(CardDeck).join(Deck).where(deck_q) elif seg[0] == 'tag': if seg[1] == '=': query = query.switch(cls).join(Note).join(NoteTag).join(Tag)\ .where(Tag.name == seg[2]) else: query = query.switch(cls).join(Note).join(NoteTag).join(Tag)\ .where(Tag.name.contains(seg[2])) else: if seg[1] == '=': query = query.switch(cls).join(Note).where(Note.data[seg[0]] == seg[2]) elif seg[1] == '>': query = query.switch(cls).join(Note).where(Note.data[seg[0]] > seg[2]) elif seg[1] == '<': query = query.switch(cls).join(Note).where(Note.data[seg[0]] < seg[2]) else: query = query.switch(cls).join(Note).where(Note.data[seg[0]].contains(seg[2])) if due is True: query = query.switch(cls).where(cls.next_review < datetime.now()) elif due is False: query = query.switch(cls).where(cls.next_review.is_null(True)) elif isinstance(due, timedelta): query = query.switch(cls).where(cls.next_review < datetime.now() + due) elif isinstance(due, datetime): query = query.switch(cls).where(cls.next_review < due) else: if not due_is_set: query = query.where((cls.next_review < datetime.now()) | cls.next_review.is_null(True)) if deck: query = query.switch(cls).join(CardDeck).join(Deck).where(Deck.name.startswith(deck + '::') | (Deck.name == deck)) if tags: for tag in tags: query = query.switch(cls).join(Note).join(NoteTag).join(Tag).where(Tag.name.contains(tag)) query = query.order_by(cls.next_review.desc()) if offset: query = query.offset(offset) if limit: query = query.limit(limit) return query
class User(BaseModel): email = pw.CharField(max_length=80, unique=True) password = pw.CharField() joined_on = pw.DateTimeField()
class Appointment(BaseModel): doctor = pw.ForeignKeyField(User, null=False) patient = pw.ForeignKeyField(User, null=False) start_datetime = pw.DateTimeField(null=False) end_datetime = pw.DateTimeField(null=False) zoom_url = pw.TextField(null=True) def validate(self): #check if 'doctor' exists doctor = User.get_or_none(User.id == self.doctor) if doctor: if "doctor" not in doctor.role: #check if 'doctor' entered is a doctor self.errors.append("IC entered does not belong to a doctor.") else: self.errors.append("User not found") #check if 'patient' exists patient = User.get_or_none(User.id == self.patient) if patient: if "patient" not in patient.role: #check if 'patient' entered is a patient self.errors.append("IC entered does not belong to a patient.") else: self.errors.append("User not found") start = datetime.strptime(self.start_datetime, '%Y-%m-%d %H:%M:%S') end = datetime.strptime(self.end_datetime, '%Y-%m-%d %H:%M:%S') #basic validation for start and end if start == end: self.errors.append("The start time and end time is the same.") if start > end: self.errors.append("The start time is later than end time.") if start.day != end.day: self.errors.append( "Appointments must be completed within the same day.") if not (start > datetime.now() and end > datetime.now()): self.errors.append("Appointments must be in the future.") # CREATE Appointment Validation Pseudocode #1. search for all records containing self.doctor, self.patient (if no record, then create appointment) #2. convert incoming datetime string into datetime object (to compare with database's DT object) #3. Validation: # a. starttime cannot be the same # b. endtime cannot be the same # c. self.start cannot in between record's start and record's end # d. self.end cannot in between record's start and record's end # e. record's start cannot in between self.start and self.end # f. record's end cannot in between self.start and self.end #EDIT Appointment Validation Pseudocode # Same as CREATE, but exclude the appointment to be edited from query if self.id: #if there is self.id --> *EDIT* appointment validation existing_appointments = Appointment.select().where( ((Appointment.doctor == self.doctor) | (Appointment.patient == self.patient)) & (~(Appointment.id == self.id))) if existing_appointments > 0: for a in existing_appointments: #loop through the records containing self.doctor, self.patient if (start == a.start_datetime) or ( end == a.end_datetime) or ( start > a.start_datetime and start < a.end_datetime) or ( end > a.start_datetime and end < a.end_datetime) or ( a.start_datetime > start and a.start_datetime < end) or ( a.end_datetime > start and a.end_datetime < end): self.errors.append( "Appointment time slot not available.") else: print( 'No other appointments for these doctor and patient. Validation passed.' ) else: #if there is no self.id --> *CREATE* appointment validation existing_appointments = Appointment.select().where( (Appointment.doctor == self.doctor) | (Appointment.patient == self.patient)) if existing_appointments > 0: for a in existing_appointments: #loop through the records containing self.doctor, self.patient if (start == a.start_datetime) or ( end == a.end_datetime) or ( start > a.start_datetime and start < a.end_datetime) or ( end > a.start_datetime and end < a.end_datetime) or ( a.start_datetime > start and a.start_datetime < end) or ( a.end_datetime > start and a.end_datetime < end): self.errors.append( "Appointment time slot not available.") else: print( 'No appointments for these doctor and patient. Validation passed.' ) print(self.errors) @hybrid_property def record(self): from models.record import Record from models.patient_photo import Patient_Photo r = Record.get_or_none(Record.appointment_id == self.id) if r: result = { "record_id": r.id, "appointment_id": r.appointment_id, "report": r.report, "prescription": r.prescription, "payment_amount": str(r.payment_amount), "paid": r.paid, "cholestrol_level": str(float(r.cholestrol_level)), "sugar_level": str(float(r.sugar_level)), "systolic_blood_pressure": str(float(r.systolic_blood_pressure)), "diastolic_blood_pressure": str(float(r.diastolic_blood_pressure)), "doctor_name": r.appointment.doctor.name, "doctor_ic": r.appointment.doctor.ic_number, "patient_name": r.appointment.patient.name, "patient_ic": r.appointment.patient.ic_number, "record_photo": r.photo } else: result = None return result def error(self): error_message = [] for error in self.errors: error_message.append(error) response = {"message": error_message, "status": "fail"} return response
class Migration(peewee.Model): name = peewee.CharField(max_length=255) time = peewee.DateTimeField(default=datetime.datetime.now) class Meta: database = models.database
class Raffle(peewee.Model): id = peewee.IntegerField(primary_key=True) room_id = peewee.IntegerField(index=True) gift_name = peewee.CharField() gift_type = peewee.CharField() sender_obj_id = peewee.IntegerField(index=True) sender_name = peewee.CharField(null=True) winner_obj_id = peewee.IntegerField(null=True, index=True) winner_name = peewee.CharField(null=True) prize_gift_name = peewee.CharField(null=True) prize_count = peewee.IntegerField(null=True) created_time = peewee.DateTimeField(default=random_datetime, index=True) expire_time = peewee.DateTimeField(default=random_datetime, index=True) raffle_result_danmaku = peewee.CharField(null=True, max_length=20480) class Meta: database = mysql_db @classmethod async def get_by_id(cls, raffle_id): try: return await objects.get(Raffle, id=raffle_id) except peewee.DoesNotExist: return None @classmethod async def record_raffle_before_result( cls, raffle_id, room_id, gift_name, gift_type, sender_uid, sender_name, sender_face, created_time, expire_time, ): sender = await BiliUser.get_or_update(uid=sender_uid, name=sender_name, face=sender_face) try: return await objects.create( cls, id=raffle_id, room_id=room_id, gift_name=gift_name, gift_type=gift_type, sender_obj_id=sender.id, sender_name=sender_name, created_time=created_time, expire_time=expire_time, ) except peewee.IntegrityError as e: error_msg = f"{e}" if "Duplicate entry" in error_msg: old_rec = await objects.get(Raffle, id=raffle_id) old_rec.room_id = room_id old_rec.gift_name = gift_name old_rec.gift_type = gift_type old_rec.sender_obj_id = sender.id old_rec.sender_name = sender_name old_rec.created_time = created_time old_rec.expire_time = expire_time await objects.update(old_rec) return old_rec return None @classmethod async def create( cls, raffle_id, room_id, gift_name, gift_type, sender_uid, sender_name, sender_face, created_time, expire_time, prize_gift_name, prize_count, winner_uid, winner_name, winner_face, **kw ): sender = await BiliUser.get_or_update(uid=sender_uid, name=sender_name, face=sender_face) winner = await BiliUser.get_or_update(uid=winner_uid, name=winner_name, face=winner_face) try: return await objects.create( cls, id=raffle_id, room_id=room_id, gift_name=gift_name, gift_type=gift_type, sender_obj_id=sender.id, sender_name=sender_name, winner_obj_id=winner.id, winner_name=winner_name, prize_gift_name=prize_gift_name, prize_count=prize_count, created_time=created_time, expire_time=expire_time ) except peewee.IntegrityError as e: if "Duplicate entry" in f"{e}": old_rec = await objects.get(Raffle, id=raffle_id) old_rec.room_id = room_id old_rec.prize_gift_name = prize_gift_name old_rec.prize_count = prize_count old_rec.sender_obj_id = sender.id old_rec.winner_obj_id = winner.id await objects.update( obj=old_rec, only=("room_id", "prize_gift_name", "prize_count", "sender_obj_id", "winner_obj_id") ) return old_rec return None @classmethod async def update_raffle_result( cls, raffle_obj, prize_gift_name, prize_count, winner_uid, winner_name, winner_face, danmaku_json_str="" ): sender = await BiliUser.get_or_update(uid=winner_uid, name=winner_name, face=winner_face) raffle_obj.prize_gift_name = prize_gift_name raffle_obj.prize_count = prize_count raffle_obj.winner_obj_id = sender.id raffle_obj.winner_name = winner_name raffle_obj.raffle_result_danmaku = danmaku_json_str await objects.update( obj=raffle_obj, only=("prize_gift_name", "prize_count", "winner_obj_id", "winner_name", "raffle_result_danmaku") ) return raffle_obj
class Album(BaseTable): artist = peewee.ForeignKeyField(Artist) title = peewee.CharField() release_date = peewee.DateTimeField() publisher = peewee.CharField() media_type = peewee.CharField()
class BiliUser(peewee.Model): uid = peewee.IntegerField(unique=True, null=True, index=True) name = peewee.CharField(index=True) face = peewee.CharField() user_info_update_time = peewee.DateTimeField(default=random_datetime) short_room_id = peewee.IntegerField(null=True, unique=True) real_room_id = peewee.IntegerField(null=True, unique=True, index=True) title = peewee.CharField(default="") create_at = peewee.CharField(default="2010-12-00 00:00:00") attention = peewee.IntegerField(default=0) guard_count = peewee.IntegerField(default=0) room_info_update_time = peewee.DateTimeField(index=True, default=random_datetime) class Meta: database = mysql_db @classmethod async def get_uid_by_name(cls, name): try: user = await objects.get(cls, name=name) return user.uid except peewee.DoesNotExist: return None @classmethod async def get_or_update(cls, uid, name, face=""): if uid is None: try: return await objects.get(BiliUser, name=name) except peewee.DoesNotExist: user_obj = await objects.create( BiliUser, name=name, face=face, user_info_update_time=datetime.datetime.now() ) return user_obj try: user_obj = await objects.get(BiliUser, uid=uid) if user_obj.name != name: user_obj.name = name user_obj.face = face user_obj.user_info_update_time = datetime.datetime.now() await objects.update(user_obj, only=("name", "face", "user_info_update_time")) return user_obj except peewee.DoesNotExist: # 不能通过uid来获取user obj, 但name不为空, 库中可能存在user name跟此条相同的记录 # 直接创建的话,可能会造成很多重复记录 因此找出已经存在的记录 更新之 try: existed_user_obj = await objects.get(BiliUser, name=name) existed_user_obj.uid = uid existed_user_obj.face = face existed_user_obj.user_info_update_time = datetime.datetime.now() await objects.update(existed_user_obj, only=("uid", "face", "user_info_update_time")) return existed_user_obj except peewee.DoesNotExist: # 既不能通过uid来获取该记录,也没有存在的name,则完整创建 user_obj = await objects.create( BiliUser, name=name, uid=uid, face=face, user_info_update_time=datetime.datetime.now() ) return user_obj @classmethod async def get_by_uid(cls, uid): objs = await objects.execute(BiliUser.select().where(BiliUser.uid == uid)) return objs[0] if objs else None @classmethod async def full_create_or_update( cls, uid, name, face, user_info_update_time, short_room_id, real_room_id, title, create_at, attention, guard_count, room_info_update_time ): obj = await cls.get_by_uid(uid) if not obj: objs = await objects.execute(cls.select().where(cls.real_room_id == real_room_id)) if objs: obj = objs[0] if obj: obj.name = name obj.face = face obj.user_info_update_time = user_info_update_time obj.short_room_id = short_room_id obj.real_room_id = real_room_id obj.title = title obj.create_at = create_at obj.attention = attention obj.guard_count = guard_count obj.room_info_update_time = room_info_update_time await objects.update(obj) else: obj = await objects.create( cls, uid=uid, name=name, face=face, user_info_update_time=user_info_update_time, short_room_id=short_room_id, real_room_id=real_room_id, title=title, create_at=create_at, attention=attention, guard_count=guard_count, room_info_update_time=room_info_update_time ) return obj @classmethod async def get_by_uid_or_name(cls, uid_or_name): try: user = await objects.get(cls, uid=int(uid_or_name)) return user except (TypeError, ValueError, peewee.DoesNotExist): pass try: user = await objects.get(cls, name=uid_or_name) return user except (TypeError, ValueError, peewee.DoesNotExist): pass
class CreditTimestamp(DdmBotSchema): last = peewee.DateTimeField()
class Reading(db_wrapper.Model): timestamp = peewee.DateTimeField() sensor = peewee.ForeignKeyField(Sensor, backref="readings") temperature = peewee.FloatField()
class BaseModel(Model): created_at = pw.DateTimeField(default=datetime.utcnow) class Meta: database = config.get_db()
class Visual_File(File_Model): """ The table to store visual files. Also includes the necessary functions to extract world coordinates from coordinate on the image Sorry, this class is a bit of a mess, I probably should have made separate functions to create the images. """ file_name_format = Config.file_storage.img file_path_format = Config.storage_path.img #: The type of visual (either image for video) visual_type = pw.CharField() #: The extension of the file extension = pw.CharField() #: The generator used to create the visual visual_generator = pw.CharField(null=True) #: An optional description of the generated visual description = pw.CharField(default="NA") #: The time the visual was generated time_generated = pw.DateTimeField(default=datetime.datetime.now) # The following 4 float fields hold the normalized image coordinate describing the location of the actual image on the picture. # # Actual Image (1,1) # ^ +------------------------------------------+ # | | | # +-------> | | +-------------------------------+ | # | | | | | | # | | | | | | # | | | | | | # | Height | | | | | # | in | | | | | # | im_ur_y Pixels | | | Solar Picture | | # | | | | | | # | | | | | | # | | | | | | # | | | | | | # | | | | | | # | | | | | | # | +--> | | +-------------------------------+ | # | | | | | # | im_ll_y | | | | # + + + +------------------------------------------+ # (0,0) # +------------------------------------------> # Width in pixels # ^ # +--------+ # im_ll_x ^ # im_ur_x | # +---------------------------------------+ # # # This scheme allows, along with the header data of the fits file that generated # the image, a strnslation between point on the actual picture, and point in # in the world im_ll_x = pw.FloatField(default=0) im_ll_y = pw.FloatField(default=0) im_ur_x = pw.FloatField(default=0) im_ur_y = pw.FloatField(default=0) width = pw.FloatField(default=0) height = pw.FloatField(default=0) @staticmethod def create_new_visual( input_file: Any, visual_builder: Any, save_format: str = Config.storage_path.img, file_name_format: str = Config.file_storage.img, desc: str = "", overwrite=True, ): """ Create a new visual. This is a wrapper that uses a :class:`~solar.visual.base_visual.Visual_Builder` to create new files and automatically add them to the database. Information about the actual image generation can be found in :doc:`/visuals/index`. :param input_file: The :class:`~solar.database.tables.fites_file.Fits_File` to be used in generating the images. :type input_file: Either a list or a single :class:`~solar.database.tables.fites_file.Fits_File` :param visual_builder: The :class:`~solar.visual.base_visual.Visual_Builder` to use to generate the images :type visual_builder: :class:`~solar.visual.base_visual.Visual_Builder` :param save_format: The format to save the files :type save_format: str :param file_save_format: The format for the file name :type save_format: str :param desc: Optional Description :type save_format: str :param overwrite: Whether to overwrite existing files. If true aborts if a file that elready exists would be generated :type save_format: bool """ btype = type(visual_builder) if issubclass(btype, Video_Builder): chat("Looks like you want me to create a video") return Visual_File.__create_new_video( input_file, visual_builder, save_format, file_name_format, desc, overwrite, ) if issubclass(btype, Image_Builder): if isinstance(input_file, Fits_File): chat("Looks like you want me to create an image") return Visual_File.__create_new_image( input_file, visual_builder, save_format, file_name_format, desc, overwrite, ) else: chat("Looks like you want me to create several images image") return [ Visual_File.__create_new_image( x, visual_builder, save_format, file_name_format, desc, overwrite, ) for x in input_file ] @staticmethod def __make_fname(fits, image_maker): file_name = Path(fits.file_name).stem file_name = str( Path(file_name).with_suffix("." + image_maker.extension)) return file_name @staticmethod def __make_path_name(fits, image_maker, save_format, file_name): file_path = dbformat( save_format, fits, file_name=file_name, extension=image_maker.extension, event_id=fits.event.event_id, ) return dbroot(file_path) @staticmethod def __delete(im): for x in im.fits_join: x.delete_instance() im.delete_instance() @staticmethod def __try_create_visual(file_path, file_name, visual_builder, desc): try: im = Visual_File.get(Visual_File.file_path == file_path) already_exists = True chat("Looks like there is already a image at this file path") except pw.DoesNotExist: im = Visual_File( file_path=file_path, file_name=file_name, visual_type=visual_builder.visual_type, visual_generator=visual_builder.generator_name, extension=visual_builder.extension, description=desc, im_ll_x=visual_builder.im_ll_x, im_ll_y=visual_builder.im_ll_y, im_ur_x=visual_builder.im_ur_x, im_ur_y=visual_builder.im_ur_y, width=visual_builder.width, height=visual_builder.height, ) already_exists = False chat( "I couldn't find an existing image, so I am going to create a new one." ) except Exception as e: im = None already_exists = False print(e) return (im, already_exists) @staticmethod def __report_status(name, exists, overwrite): if exists and not overwrite: chat( f"This {name} exists and overwrite is false, so I am not going to continue" ) return False if exists and overwrite: chat( f"This {name} seems to already exist, but since you have selected overwrite, I am going to replace it with a new one" ) return True if not exists: chat( f"This {name} doesn't seem to exist, so I am creating a new one" ) return True def __assign_generated_parameters(self, visual_builder): self.im_ll_x = visual_builder.im_ll_x self.im_ll_y = visual_builder.im_ll_y self.im_ur_x = visual_builder.im_ur_x self.im_ur_y = visual_builder.im_ur_y self.width = visual_builder.width self.height = visual_builder.height return self @staticmethod def __create_new_image( input_file: Any, visual_builder: Any, save_format: str = Config.storage_path.img, file_name_format: str = Config.file_storage.img, desc: str = "", overwrite=True, ): base_fits = input_file file_name = dbformat(file_name_format, base_fits, visual_builder) print(base_fits.file_name.stem) full_path = dbpathformat(file_name_format, save_format, base_fits, visual_builder, base_fits.event) im, exists = Visual_File.__try_create_visual(full_path, file_name, visual_builder, desc) source_path = base_fits.file_path if not Visual_File.__report_status("image", exists, overwrite): return None created = visual_builder.create(source_path) if not created: return None visual_builder.save_visual(base_fits, full_path) im.__assign_generated_parameters(visual_builder) im.save() join = Visual_File.__get_create_join(im, base_fits) join.save() im.get_hash() return im @staticmethod def __create_new_video( input_files: Any, visual_builder: Any, save_format: str = Config.storage_path.img, file_name_format: str = Config.file_storage.img, desc: str = "", overwrite=True, base_fits=None, ): base_fits = base_fits if base_fits else input_files[0] file_name = dbformat(file_name_format, base_fits, visual_builder) full_path = dbpathformat(file_name_format, save_format, base_fits, visual_builder, base_fits.event) im, exists = Visual_File.__try_create_visual(full_path, file_name, visual_builder, desc) source_paths = [x.file_path for x in input_files] if not Visual_File.__report_status("video", exists, overwrite): return None created = visual_builder.create(source_paths) if not created: return None visual_builder.save_visual(base_fits, full_path) im.__assign_generated_parameters(visual_builder) im.set_visual_hash() im.save() joins = Visual_File.__get_joins(im, input_files) for j in joins: j.save() im.get_hash() return im @staticmethod def __get_joins(vis, fits): return [Visual_File.__get_create_join(vis, x) for x in fits] @staticmethod def __get_create_join(vis, fits): from .join_vis_fit import Join_Visual_Fits try: join = (Join_Visual_Fits.select().join(Visual_File).where( Join_Visual_Fits.fits_file == fits, Join_Visual_Fits.visual_file == vis, Visual_File.file_hash == vis.file_hash, ).get()) chat( f"I found an existing join from this visual (id = {vis.id}) to the fits file id={fits.id}, so I am going to use it. Both images has a file hash {vis.file_hash}." ) except pw.DoesNotExist: join = Join_Visual_Fits(fits_file=fits, visual_file=vis) chat( f"I could not find an existing visual for fits file with id {fits.id}, so I am creating a new one" ) # join = Join_Visual_Fits(fits_file=fits, visual_file=vis) return join def pixel_from_world(self, hpc_x, hpc_y, normalized=False): """ Get the pixel coordinate from a world coordinate """ fits = self.fits_join.get().fits_file header_dict = FileHeader(fits.get_header_as_dict()) fake_map = Map(np.zeros((1, 1)), header_dict) return mp.pixel_from_world(fake_map, self, hpc_x, hpc_y, normalized=normalized) def world_from_pixel(self, x, y): """ Get a world coordinate from a pixel on the image. :rtype: sunpy coordinate """ if x > 1 and y > 1: return self.__world_from_pixel_abs(x, y) else: return self.__world_from_pixel_norm(x, y) def world_from_pixel_value(self, x, y): """Returns the HPC coordinate from a pixel coordinate as a tuple. """ v = self.world_from_pixel(x, y) return v.spherical.lon.arcsec, v.spherical.lat.arcsec def __world_from_pixel_abs(self, x: int, y: int): return self.__world_from_pixel_norm(x / self.width, y / self.height) def __world_from_pixel_norm(self, x: float, y: float) -> Any: fits = self.fits_join.get().fits_file header_dict = FileHeader(fits.get_header_as_dict()) fake_map = Map(np.zeros((1, 1)), header_dict) return mp.world_from_pixel_norm(fake_map, self, x, y) def get_fits(self): """ Get the fits files used to generate this image """ from .join_vis_fit import Join_Visual_Fits found = Join_Visual_Fits.select().where( Join_Visual_Fits.visual_file == self) return list(found) def __repr__(self) -> str: return f"""<vid: {self.id}>""" def __str__(self) -> str: return f""" Type = {self.visual_type} File_Path = {self.file_path} Hash = {self.file_hash} """ def __set_vis_hash(self): self.visual_hash = hash(( self.extension, self.visual_generator, self.im_ll_x, self.im_ll_y, self.im_ur_x, self.im_ur_y, self.width, self.height, ))