ck-ntuh-net/mysite/nsclc/models.py
2024-12-11 16:15:42 +08:00

287 lines
15 KiB
Python
Executable file

# coding=utf-8
# from django.core.urlresolvers import reverse
from django.urls import reverse
from django.db import models
#from ck.models import *
#from MultiSelect import *
# Create your models here.
CONTROL_CHOICES = (
('CR', 'Complete Response'),
('PR', 'Partial Response'),
('SD', 'Stable Disease'),
('PD', 'Progressive Disease'),
)
#PRIOR_TX_CHOICES = (
# (10, 'OBS=Observation'),
# (20, 'S=Surgery'),
# (30, 'CHT=Chemotherapy'),
# (40, 'TKI=Target therapy'),
# (50, 'RT=Whole brain radiotherapy'),
# )
class PriorTx(models.Model):
value = models.CharField(max_length=3, primary_key=True)
option = models.CharField(max_length=200)
def __str__(self):
return self.option
def instance_fields(instance):
"""Returns a list of all field names on the instance."""
fields = []
for f in instance._meta.fields:
fname = f.name
# resolve picklists/choices, with get_xyz_display() function
get_choice = 'get_'+fname+'_display'
if hasattr( instance, get_choice):
value = getattr( instance, get_choice)()
else:
try :
value = getattr(instance, fname)
except:
value = None
# only display fields with values and skip some fields entirely
# if f.editable and f.name not in ('id', 'Patient') :
# if f.name not in ('id', 'Patient') :
# if not f.primary_key:
if True:
fields.append(
{
'verbose_name':f.verbose_name,
'name':f.name,
'value':value,
}
)
return fields
def instance_many_to_many(instance):
fields = []
for f in instance._meta.many_to_many:
fname = f.name
# resolve picklists/choices, with get_xyz_display() function
get_choice = 'get_'+fname+'_display'
if hasattr( instance, get_choice):
value = getattr( instance, get_choice)()
else:
try :
value = getattr(instance, fname)
except:
value = None
if value:
value = [x for x in value.all()]
fields.append(
{
'verbose_name':f.verbose_name,
'name':f.name,
'value':value,
}
)
return fields
class NPatient(models.Model):
# Patient = models.ForeignKey('ck.Patient', primary_key=True)
Patient = models.OneToOneField('ck.Patient', primary_key=True, on_delete=models.CASCADE)
LastModified = models.DateTimeField(auto_now = True)
# Name = models.CharField(max_length=200, verbose_name='病患姓名') # Patient Name
# ChartID = models.IntegerField(primary_key=True, verbose_name='病歷號碼') # Chart Number
# DOB = models.DateField( verbose_name='出生年月日') # Date of Birth
#
# SEX_CHOICES = (
# (1, 'Male'),
# (2, 'Female'),
# )
# Sex = models.IntegerField(choices=SEX_CHOICES, verbose_name='性別') # Gender
DxDate = models.DateField(null=True, blank=True, verbose_name='診斷日期') # Date of Diagnosis
HISTOLOGY_CHOICES = (
(1, 'Adenocarcinoma'),
(2, 'Squamous cell carcinoma'),
(3, 'Large cell carcinoma'),
(4, 'carcinoma, NOS'),
(5, 'Adenosquamous carcinoma'),
)
Histology = models.IntegerField(choices=HISTOLOGY_CHOICES, null=True, blank=True, verbose_name='組織學型態') # Histology Subtypes
BMDate = models.DateField(null=True, blank=True, verbose_name='初次腦轉移日期') # First Date of Diagnosis of Brain Metastases
KPS70 = models.BooleanField(null=True, verbose_name='行為狀態量表至少七十分以上') # Karnovsky Performance Status ≥70
ExtraCranialMets = models.BooleanField(null=True, verbose_name='是否有胸腔外轉移病灶') # Presence of Extrathoracic Metastasis
DistantControl = models.CharField(max_length=2, choices=CONTROL_CHOICES, null=True, blank=True, verbose_name='三個月內顱外轉移控制狀態') # Control of Extracranial Metastasis within 3 M
PrimaryControl = models.BooleanField(null=True,verbose_name='胸腔原發部位控制狀態(Controlled)') # Control of Primary (Thoracic) Disease
UpfrontSRS = models.BooleanField(null=True,verbose_name='腦轉移診斷後是否即刻進行電腦刀治療') # Upfront SRS after BM diagnosis
PRIOR_TX_CHOICES = (
('OBS', 'Observation'),
('S', 'Surgery'),
('CHT', 'Chemotherapy'),
('TKI', 'Target therapy'),
('RT', 'Whole brain radiotherapy'),
)
# PRIOR_TX_CHOICES = (
# (10, 'OBS=Observation'),
# (20, 'S=Surgery'),
# (30, 'CHT=Chemotherapy'),
# (40, 'TKI=Target therapy'),
# (50, 'RT=Whole brain radiotherapy'),
# )
# PriorTx = models.CharField(max_length=3, choices=HISTOLOGY_CHOICES, null=True, verbose_name='若非即刻進行電腦刀之治療方式') # Any Tx if SRS is deferred
# PriorTx = models.CommaSeparatedIntegerField(max_length=5, choices=PRIOR_TX_CHOICES, null=True, verbose_name='若非即刻進行電腦刀之治療方式') # Any Tx if SRS is deferred
# PriorTx = MultiSelectField(max_length=5, choices=PRIOR_TX_CHOICES, null=True, verbose_name='若非即刻進行電腦刀之治療方式') # Any Tx if SRS is deferred
priortx = models.ManyToManyField(PriorTx, blank=True, verbose_name='若非即刻進行電腦刀之治療方式') # Any Tx if SRS is deferred
PriorWBRT = models.BooleanField(null=True, verbose_name='曾接受全腦放射治療') # History of Prior Whole Brain Radiotherapy
WBRTDate = models.DateField( null=True, blank=True, verbose_name='全腦放射治療日期') # Start Date of Prior WBRT
AdjuvantWBRT = models.BooleanField(null=True, verbose_name='電腦刀後八週內進行全腦放射治療') # WBRT Within 2 Months after SRS
SRSBMDate = models.DateField( null=True, blank=True, verbose_name='進行電腦刀之腦轉移診斷日期') # Diagnosis of Brain Metastsis for SRS
BMnumber = models.IntegerField(null=True, blank=True, verbose_name='電腦刀治療腦轉移病灶總數量') # Number of Brain Mets for SRS
##########
TKI = models.BooleanField(null=True,verbose_name='同時使用標靶治療') # Concurrent Use of TKI
##########
Radionecrosis = models.BooleanField(null=True, verbose_name='放射性壞死') # Presence of Radionecrosis
# Pseudoprogression = models.BooleanField(null=True, verbose_name='MRI影像判讀偽惡化') # Pseudoprogression on MRI/MRS/MRP
RNDate = models.DateField(null=True, blank=True, verbose_name='診斷放射性壞死日期') # Date of Radionecrosis or Censor
NewBM = models.BooleanField(null=True, verbose_name='發生新腦轉移病灶') # Presence of New Brain Metastsis
NEW_BM_NUMBER_CHOICES = (
('1', '1'),
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5'),
('M', '>5'),
)
NewBMNumber = models.CharField(max_length=1, choices=NEW_BM_NUMBER_CHOICES, null=True, blank=True, verbose_name='新腦轉移病灶數量') # Number of New Brain Metastasis
NewBMDate = models.DateField(null=True, blank=True, verbose_name='診斷新腦轉移病灶日期') # Date of New Brain Metastasis or Censor
SALVAGE_TX_CHOICES = (
(0, 'Supportive care'),
(1, 'Chemotherapy'),
(2, 'Target therapy'),
(3, 'WBRT'),
(4, 'SRS'),
(5, 'Surgery'),
)
SalvageTx = models.IntegerField(choices=SALVAGE_TX_CHOICES, null=True, blank=True, verbose_name='新腦轉移病灶治療方法') # Salvage Treatment
Death = models.BooleanField(null=True, verbose_name='發生死亡事件') # Death
NeuroDeath = models.BooleanField(null=True, verbose_name='因腦轉移導致死亡') # Neurogenic Death Due to Brain Metastasis
SurviveDate = models.DateField(null=True, blank=True, verbose_name='存活日期') # Date of Death or Censor
DistantProgression = models.BooleanField(null=True, verbose_name='顱外病灶惡化') # Progression of Extracranial Disease
DistantDate = models.DateField(null=True, blank=True, verbose_name='顱外病灶惡化日期') # Date of Extracranial Progression or Censor
PoorKPS = models.BooleanField(null=True, verbose_name='行為狀態惡化致生活無法自理') # Progression of Extracranial Disease
DependentDate = models.DateField(null=True, blank=True, verbose_name='生活開始無法自理日期') # Date of KPS < 70 or Censor
##########
EGFR = models.CharField(max_length=200, blank=True, null=True, verbose_name='EGFR Mutation Status')
ALK = models.CharField(max_length=200, blank=True, null=True, verbose_name='EML4-ALK Rearrangement')
KRAS = models.CharField(max_length=200, blank=True, null=True, verbose_name='K-RAS Mutation Status')
BRAF = models.CharField(max_length=200, blank=True, null=True, verbose_name='BRAF Mutation Status')
HER2 = models.CharField(max_length=200, blank=True, null=True, verbose_name='HER2 Mutation Status')
ThoracicMets = models.BooleanField(null=True, verbose_name='是否有胸腔轉移病灶') # Presence of intrathoracic Metastasis
SalvageWBRT = models.BooleanField(null=True, verbose_name='是否接受救援全腦放射治療') # Salvage WBRT after SRS
SalvageRTDate = models.DateField(null=True, blank=True, verbose_name='救援全腦放射治療日期') # Date of salvage WBRT
SRSDate = models.DateField(null=True, blank=True, verbose_name='執行第一次SRS日期') # Date of first SRS treatment
OverallResponse = models.CharField(max_length=2, choices=CONTROL_CHOICES, null=True, blank=True, verbose_name='RECIST整體最佳反應') # Combined best response according to RECIST
LocalProgression = models.BooleanField(null=True, verbose_name='RECIST整體局部病灶惡化') # Combined progression according to RECIST
LocalDate = models.DateField(null=True, blank=True, verbose_name='RECIST局部病灶惡化日期') # Date of Local Progression
PseudoPD = models.BooleanField(null=True, verbose_name='偽惡化') # Pseudoprogression
ClinicalProgression = models.BooleanField(null=True, verbose_name='臨床評估局部復發') # Clinical local control
RecurDate = models.DateField(null=True, blank=True, verbose_name='臨床評估局部復發日期') # Date of clinical local progression
LateSE = models.IntegerField(null=True, blank=True, verbose_name='SRS副作用嚴重程度') # Grading of Late Toxicity
def Physician(self):
p = None
for t in self.Patient.treatment_set.all():
if t.surgeon:
return {
'dept': 'surg',
'name': t.surgeon,
}
else:
p = t.oncologist
return {
'dept': 'onc',
'name': p,
}
def get_absolute_url(self):
# return reverse('patient_update', kwargs={'pk': self.Patient.id})
return reverse('patient_update', args=[self.Patient.id])
def meta(self):
return self._meta
def fields(self):
return instance_fields(self)
def many_to_many(self):
return instance_many_to_many(self)
class NTarget(models.Model):
# Lesion = models.ForeignKey('ck.Lesion', primary_key=True)
Lesion = models.OneToOneField('ck.Lesion', primary_key=True, on_delete=models.CASCADE)
LastModified = models.DateTimeField(auto_now = True)
# TargetID = models.IntegerField(primary_key=True, verbose_name='電腦刀腦轉移病灶編號') # ID of Brain Mets Target for SRS
RECIST = models.BooleanField(null=True, blank=True, verbose_name='是否為RECIST可測量病灶') # RECIST Measurable Lesion
BMdiameter = models.FloatField( null=True, blank=True, verbose_name='病灶最大直徑(mm)') # Diameter of Brain Metastasis
# BMvolume = models.FloatField( verbose_name='病灶體積(mL)') # Volume of Brain Metatasis
# SRSdose = models.IntegerField( verbose_name='處方劑量(cGy)') # Prescribe SRS Dose
# Fraction = models.IntegerField( verbose_name='治療次數') # Number of SRS fraction
# Isodose = models.IntegerField( verbose_name='百分等劑量線(%)') # Prescribed Isodose Line
PTV = models.BooleanField(null=True,verbose_name='是否外加PTV邊界') # Additional PTV to Brain Metastasis
# MinDose = models.FloatField( verbose_name='百分之九九病灶體積接受劑量(cGy)') # Actual Dose Covering 99% of Target
# MaxDose = models.FloatField( verbose_name='病灶最高劑量(cGy)') # Maximal Dose to Target
##########
# SRSDate = models.DateField(verbose_name='電腦刀治療日期') # Treatment Date of SRS
TargetResponse = models.CharField(max_length=2, choices=CONTROL_CHOICES, null=True, blank=True, verbose_name='RECIST最佳反應') # Best Response of Target
TargetControl = models.BooleanField(null=True, verbose_name='電腦刀治療病灶惡化(RECIST)') # RECIST Progression of SRS Target
TargetControlDate = models.DateField(null=True, blank=True, verbose_name='電腦刀治療病灶惡化日期') # Date of SRS Target Progression or Censor
Pseudoprogression = models.BooleanField(null=True, verbose_name='MRI影像判讀偽惡化') # Pseudoprogression on MRI/MRS/MRP
def get_absolute_url(self):
return reverse('target_update', args=[self.Lesion.id])
def fields(self):
return instance_fields(self)