o
    b4hL                     @   s
  d dl mZ d dlZd dlmZ d dlZd dlZd dl	m
Z
 d dlZd dlmZmZ d dlmZ d dlmZmZ dd Zd	d
 Zdd ZG dd de
jZG dd de
jZG dd de
jZG dd de
jZG dd de
jZG dd de
jZG dd dejZ dS )    )divisionN)hd)SpecificityJaccardIndex)BinaryAccuracy)SensitivityHausdorffDistancec                   C   s   t jdddS )z 3D max pooling for downsampling.   kernel_sizestride)nn	MaxPool3d r   r   */home/xmoravc/AI_project/model/csnet_3d.py
downsample   s   r   c                 C   s   t j| |dddS )z)3D transposed convolution for upsampling.r	   r
   )r   ConvTranspose3d)in_channelsout_channelsr   r   r   deconv   s   r   c                  G   s   | D ];}|  D ]4}t|tjst|tjr)tj|j |jdur(|jj	
  qt|tjr<|jj	d |jj	
  qqdS )zEInitialize weights using Kaiming normal for Conv3D and Linear layers.N   )modules
isinstancer   Conv3dLinearinitkaiming_normalweightbiasdatazero_BatchNorm3dfill_)modelsmodelmr   r   r   initialize_weights   s   
r&   c                       (   e Zd ZdZ fddZdd Z  ZS )ResEncoder3dz@Residual block with two Conv3D layers and a 1x1 skip connection.c                    sr   t t|   tj||ddd| _t|| _tj||ddd| _t|| _	tj
dd| _tj||dd| _d S )N   r   r   paddingFinplacer   )superr(   __init__r   r   conv1r!   bn1conv2bn2ReLUreluconv1x1selfr   r   	__class__r   r   r0   &   s   zResEncoder3d.__init__c                 C   sL   |  |}| | | |}| | | |}|| }| |}|S N)r7   r6   r2   r1   r4   r3   )r9   xresidualoutr   r   r   forward/   s   

zResEncoder3d.forward__name__
__module____qualname____doc__r0   r@   __classcell__r   r   r:   r   r(   $       	r(   c                       r'   )	Decoder3dz%Decoder block with two Conv3D layers.c                    s`   t t|   ttj||dddt|tjddtj||dddt|tjdd| _d S )Nr)   r   r*   Fr,   )	r/   rH   r0   r   
Sequentialr   r!   r5   convr8   r:   r   r   r0   :   s   


zDecoder3d.__init__c                 C   s   |  |}|S r<   )rJ   )r9   r=   r?   r   r   r   r@   E   s   
zDecoder3d.forwardrA   r   r   r:   r   rH   8   s    rH   c                       r'   )SpatialAttentionBlock3dz7Spatial attention using anisotropic convolutions in 3D.c                    s   t t|   tj||d ddd| _tj||d ddd| _tj||d ddd| _tj||d	d
| _t	t
d	| _tjdd| _d S )N   )r   r)   r   )r   r   r   r*   )r)   r   r   )r   r   r   )r   r   r)   )r   r   r   r   r.   dim)r/   rK   r0   r   r   querykeyjudgevalue	ParametertorchzerosgammaSoftmaxsoftmaxr9   r   r:   r   r   r0   L   s   z SpatialAttentionBlock3d.__init__c                 C   s   |  \}}}}}| ||d|| | ddd}| ||d|| | }| ||d|| | ddd}	t||}
t|	|}t|
|}| |}| 	||d|| | }t||}||||||}| j
| | }|S )z
        :param x: input( BxCxHxWxZ )
        :return: affinity value + x
        B: batch size
        C: channels
        H: height
        W: width
        D: slice number (depth)
        rM   r   r	   r   )sizerP   viewpermuterQ   rR   rU   matmulrY   rS   rW   )r9   r=   BCHWD
proj_queryproj_key
proj_judge	affinity1	affinity2affinity
proj_valueweightsr?   r   r   r   r@   U   s   
&&
zSpatialAttentionBlock3d.forwardrA   r   r   r:   r   rK   J   rG   rK   c                       r'   )ChannelAttentionBlock3dz&Channel-wise attention for 3D volumes.c                    s2   t t|   ttd| _tjdd| _	d S )Nr   rM   rN   )
r/   rl   r0   r   rT   rU   rV   rW   rX   rY   rZ   r:   r   r   r0   s   s   z ChannelAttentionBlock3d.__init__c                 C   s   |  \}}}}}|||dddd}|||d}|||dddd}	t||}
t||	}t|
|}tj|dddd || }| |}|||d}t||}||||||}| j| | }|S )zR
        :param x: input( BxCxHxWxD )
        :return: affinity value + x
        rM   r   r	   r   T)keepdim)	r[   r\   r]   rU   r^   max	expand_asrY   rW   )r9   r=   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   Zaffinity_newrj   rk   r?   r   r   r   r@   x   s   
zChannelAttentionBlock3d.forwardrA   r   r   r:   r   rl   q       rl   c                       r'   )AffinityAttention3dzBAffinity attention combining spatial and channel attention for 3D.c                    s&   t t|   t|| _t|| _d S r<   )r/   rq   r0   rK   sabrl   cabrZ   r:   r   r   r0      s   
zAffinityAttention3d.__init__c                 C   s$   |  |}| |}|| | }|S )z
        sab: spatial attention block
        cab: channel attention block
        :param x: input tensor
        :return: sab + cab
        )rr   rs   )r9   r=   rr   rs   r?   r   r   r   r@      s   

zAffinityAttention3d.forwardrA   r   r   r:   r   rq      rp   rq   c                       r'   )CSNet3DzPCSNet3D: A full encoder-decoder 3D segmentation network with affinity attention.c                    s   t t|   t|d| _tdd| _tdd| _tdd| _tdd| _t	 | _	t
d| _tjdddd| _tdd| _tdd| _tdd| _tdd| _tdd| _tdd| _tdd| _tdd| _tjd|dd| _t|  d	S )
zv
        :param classes: the object classes number.
        :param channels: the channels of the input image.
               @         i   r   r.   N)r/   rt   r0   r(   	enc_inputencoder1encoder2encoder3encoder4r   rq   affinity_attentionr   r   attention_fuserH   decoder4decoder3decoder2decoder1r   deconv4deconv3deconv2deconv1finalr&   )r9   classeschannelsr:   r   r   r0      s&   
zCSNet3D.__init__c                 C   s  |  |}| |}| |}| |}| |}| |}| |}| |}	| |	}
| |
}|
| }| |}tj	||fdd}| 
|}| |}tj	||fdd}| |}| |}tj	||fdd}| |}| |}tj	||fdd}| |}| |}t|}|S )Nr   rN   )rz   r   r{   r|   r}   r~   r   r   rU   catr   r   r   r   r   r   r   r   sigmoid)r9   r=   rz   Zdown1Zenc1Zdown2Zenc2Zdown3Zenc3Zdown4Zinput_feature	attentionr   Zup4Zdec4Zup3Zdec3Zup2Zdec2Zup1Zdec1r   r   r   r   r@      s4   



















zCSNet3D.forwardrA   r   r   r:   r   rt      s    rt   c                       sx   e Zd ZdZ		d fdd	Zd	d
 Zdd Zdd Zdd Zdd Z	dddZ
dd Zdd Zdd Zdd Z  ZS )CSNet3DLightningaQ  
    PyTorch LightningModule for CSNet3D training, validation, and testing.

    This module wraps the 3D segmentation model and provides complete metric tracking,
    optional tiny-structure evaluation, and Hausdorff distance measurement.

    Args:
        classes (int): Number of output classes (usually 1).
        channels (int): Number of input channels.
        lr (float): Learning rate.
        threshold (float): Threshold for converting probabilities to binary predictions.
        noise (float): Noise label for saved sample naming.
        log_to_logger (bool): Enable/disable logging to the Lightning logger.
        tiny_structures_eval (bool): Evaluate small structures separately using mask.
        model_noise (float): Distinguishing tag for saving.
        eval_hd (bool): Enable Hausdorff distance computation using MedPy.
    -C6?      ?r   TFc	           	         sZ  t t|   t||| _|| _|   g | _g | _|| _	t
 | _d| _g | _|| _|| _td| j  t|dt|dtd|dddtd|dddtd	|d
dt|dt|dtd|dddtd|dddtd	|d
dt|dt|dtd|dddtd|dddtd	|d
dd| _tjtj| jddd tjtj| jddd d S )Nz	./sampleszSelf eval_hd: )	thresholdr   microbinary)num_classesr   averagetaskmacro_   )
percentiler   )accuracysensitivityspecificityjaccardhausdorff_distancenone)trainvaltest
validationT)exist_okr   )r/   r   r0   rt   r$   lrsave_hyperparametersZvalidation_samplesZtest_samplesr   r   BCELoss	criterionsamples_pathtest_outputslog_to_loggereval_hdprintr   r   r   r   r   metricsosmakedirspathjoin)	r9   r   r   r   r   noiser   Zmodel_noiser   r:   r   r   r0      sD   



zCSNet3DLightning.__init__c                 C   s
   |  |S r<   )r$   )r9   r=   r   r   r   r@   !  s   
zCSNet3DLightning.forwardc                    s<   t jj j  jdd}t jj| fdd}||dS )NgMb@?)r   weight_decayc                    s   d|  j j  d S )Nr   g?)trainer
max_epochs)epochr9   r   r   <lambda>'      z7CSNet3DLightning.configure_optimizers.<locals>.<lambda>)	optimizerlr_scheduler)rU   optimAdamWr$   
parametersr   r   LambdaLR)r9   r   	schedulerr   r   r   configure_optimizers$  s
   


z%CSNet3DLightning.configure_optimizersc                 C   D   | j }| jD ]}| j| D ]}| j| | || j| |< qqd S r<   devicer   tor9   r   stagerQ   r   r   r   on_fit_start*     
 zCSNet3DLightning.on_fit_startc                 C   r   r<   r   r   r   r   r   on_test_start0  r   zCSNet3DLightning.on_test_startc                 C   s   |\}}}t |j| j| }| |}| ||}|d ||}	|d ||}
|d ||}|d ||}| jrD|d ||\}}nt dt d}}||||||	|
||||fS )Nr   r   r   r   r   rM   )rU   onesshaper   r   r   r   tensor)r9   batchr   imagestargetsopenedZtiny_structures_maskpredslossaccsensspecjaccmy_hdhd_95r   r   r   common_step6  s   
zCSNet3DLightning.common_stepc                 C   s   |
r| dn|}| j | d||	|	 d | j | d||	|	 d | j | d||	|	 d | j | d||	|	 d | j | d||	|	 d | jri| j | d||	|	 d | j | d	||	|	 d d S d S )
Nz tinyz losson_epochon_stepz accz sensitivityz specificityz jaccardz hausdorff distancez hausdorff distance 95)logr   )r9   r   r   r   r   r   r   r   prefixr   tinyZlog_name_prefr   r   r   log_metricsH  s   zCSNet3DLightning.log_metricsc                 C   sN   |  || jd \}}}}}}}	}
}}}| jr%| j|||	|
|||ddd	 |S )Nr   Fr   )r   r   r   r   )r9   r   	batch_idxr   r   r   tiny_struc_masksr   r   r   r   r   r   r   r   r   r   training_stepS  s   zCSNet3DLightning.training_stepc                 C   sf  |  || jd \}}}}}}}	}
}}}| jr%| j|||	|
|||ddd	 |dkrt|jd D ]}||d d d d d d d d f    }||d d d d d d d d f    }||d d d d d d d d f    }t	
tj| jdd| d|  t	
tj| jdd| d|  t	
tj| jdd	| d|  q0|S )
Nr   Tr   r   r   pred_.npyimage_target_)r   r   r   r   ranger   squeezedetachcpunpsaver   r   r   r   numpy)r9   r   r   r   r   r   r   r   r   r   r   r   r   r   iZcur_predZ	cur_imageZ
cur_targetr   r   r   validation_step[  s   ...&&(z CSNet3DLightning.validation_stepc                 C   s  |  || jd \}}}}}}}	}
}}}| jr%| j|||	|
|||ddd	 || jk}|  tj	}|  tj	}g }t
||D ]\}}t||}|| qEt|}| jre| jd|ddd |dkrt|jd D ]V}||d d d d d d d d f     }||d d d d d d d d f     }ttj| jdd	| d
| ttj| jdd| d
| qp|||	|
||||d}| j| |S )Nr   Tr   ztest hausdorff distanceFr      r   r   r   r   )r   r   r   r   r   r   my_hausdorff_distancemy_hausdorff_distance_95)r   r   r   r   r   r   r   astyper   uint8zipr   appendnanmeanr   r   r   r   r   r   r   r   r   r   r   )r9   r   r   r   r   r   r   r   r   r   r   r   r   r   Z	bin_predsgtsZhausdorff_distpredgtZhd_valZbatch_hdr   Zpred_npZimage_npoutputr   r   r   	test_stepo  s@   


22"$
zCSNet3DLightning.test_stepc                 C   s(  dd | j D }t|}t|}dd | j D }t|}|  }|  }dd | j D }t|}|  }|  }	dd | j D }
t|
}
|
  }|
  }dd | j D }t|}|  }|  }dd | j D }t|}|  }|  }dd | j D }t|}t|}d	d | j D }t|}t|}td
 td|dd|  td|dd|	  td|dd|  td|dd|  td|dd|  td|dd|  td|dd|  td|dd|  t  d S )Nc                 S      g | ]}|d  qS )r   r   .0r=   r   r   r   
<listcomp>  r   z6CSNet3DLightning.on_test_epoch_end.<locals>.<listcomp>c                 S   r  )r   r   r  r   r   r   r    r   c                 S   r  )r   r   r  r   r   r   r    r   c                 S   r  )r   r   r  r   r   r   r    r   c                 S   r  )r   r   r  r   r   r   r    r   c                 S   r  )r   r   r  r   r   r   r    r   c                 S   r  )r   r   r  r   r   r   r    r   c                 S   r  )r   r   r  r   r   r   r    r   zTest set resultesz    Loss: mean = z.3fz, var = z    Accuracy: mean = z    Sensitivity: mean = z    Specificity: mean = z    Jaccard: mean = z    Hausdorff distance: mean = z"    My Hausdorff distance: mean = z%    My Hausdorff distance 95: mean = )r   r   meanvarrU   stackitemr   )r9   Z	hd_valuesZmean_hdZvar_hdlossesZ	mean_lossZvar_lossZaccsZmean_accZvar_accZsenssZ	mean_sensZvar_sensspecsZ	mean_specZvar_specZjaccsZ	mean_jaccZvar_jaccr   Z
mean_my_hdZ	var_my_hdZmy_hd_95Zmean_my_hd_95Zvar_my_hd_95r   r   r   on_test_epoch_end  sN   











z"CSNet3DLightning.on_test_epoch_end)r   r   r   Tr   F)TF)rB   rC   rD   rE   r0   r@   r   r   r   r   r   r   r   r  r  rF   r   r   r:   r   r      s    *
(r   )!
__future__r   os.pathr   Zmedpy.metricr   r   r   rU   torch.nnr   pytorch_lightningpltorchmetricsr   r   torchmetrics.classificationr   Zutils.my_metricsr   r   r   r   r&   Moduler(   rH   rK   rl   rq   rt   LightningModuler   r   r   r   r   <module>   s(    'D