mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-09 11:30:43 +02:00
solved bug with multidetector angular conversion
git-svn-id: file:///afs/psi.ch/project/sls_det_software/svn/slsDetectorSoftware@180 951219d9-93cf-4727-9268-0efd64621fa3
This commit is contained in:
parent
b5e966bb58
commit
83ee449e3c
@ -1434,9 +1434,15 @@ float* multiSlsDetector::decodeData(int *datain, float *fdata) {
|
|||||||
for (int i=0; i<thisMultiDetector->numberOfDetectors; i++) {
|
for (int i=0; i<thisMultiDetector->numberOfDetectors; i++) {
|
||||||
if (detectors[i]) {
|
if (detectors[i]) {
|
||||||
detectors[i]->decodeData(datap, detp);
|
detectors[i]->decodeData(datap, detp);
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << "increment pointers " << endl;
|
||||||
|
#endif
|
||||||
datap+=detectors[i]->getDataBytes()/sizeof(int);
|
datap+=detectors[i]->getDataBytes()/sizeof(int);
|
||||||
detp+=detectors[i]->getTotalNumberOfChannels();
|
detp+=detectors[i]->getTotalNumberOfChannels();
|
||||||
|
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << "done " << endl;
|
||||||
|
#endif
|
||||||
// for (int j=0; j<detectors[i]->getTotalNumberOfChannels(); j++) {
|
// for (int j=0; j<detectors[i]->getTotalNumberOfChannels(); j++) {
|
||||||
// dataout[ich]=detp[j];
|
// dataout[ich]=detp[j];
|
||||||
// ich++;
|
// ich++;
|
||||||
@ -1683,7 +1689,11 @@ int multiSlsDetector::getNMods(){
|
|||||||
|
|
||||||
int multiSlsDetector::getChansPerMod(int imod){
|
int multiSlsDetector::getChansPerMod(int imod){
|
||||||
int id=-1, im=-1;
|
int id=-1, im=-1;
|
||||||
if (decodeNMod(imod, id, im)>=0) {
|
#ifdef VERBOSE
|
||||||
|
cout << "get chans per mod " << imod << endl;
|
||||||
|
#endif
|
||||||
|
decodeNMod(imod, id, im);
|
||||||
|
if (id >=0) {
|
||||||
if (detectors[id]) {
|
if (detectors[id]) {
|
||||||
return detectors[id]->getChansPerMod(im);
|
return detectors[id]->getChansPerMod(im);
|
||||||
}
|
}
|
||||||
@ -1709,6 +1719,9 @@ int multiSlsDetector::getMoveFlag(int imod){
|
|||||||
|
|
||||||
angleConversionConstant * multiSlsDetector::getAngularConversionPointer(int imod){
|
angleConversionConstant * multiSlsDetector::getAngularConversionPointer(int imod){
|
||||||
int id=-1, im=-1;
|
int id=-1, im=-1;
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << "get angular conversion pointer " << endl;
|
||||||
|
#endif
|
||||||
if (decodeNMod(imod, id, im)>=0) {
|
if (decodeNMod(imod, id, im)>=0) {
|
||||||
if (detectors[id]) {
|
if (detectors[id]) {
|
||||||
return detectors[id]->getAngularConversionPointer(im);
|
return detectors[id]->getAngularConversionPointer(im);
|
||||||
@ -2695,6 +2708,21 @@ int multiSlsDetector::setDynamicRange(int p) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int multiSlsDetector::getMaxMods() {
|
||||||
|
|
||||||
|
|
||||||
|
int ret=0, ret1;
|
||||||
|
|
||||||
|
for (int idet=0; idet<thisMultiDetector->numberOfDetectors; idet++) {
|
||||||
|
if (detectors[idet]) {
|
||||||
|
ret1=detectors[idet]->getMaxMods();
|
||||||
|
ret+=ret1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int multiSlsDetector::getMaxNumberOfModules(dimension d) {
|
int multiSlsDetector::getMaxNumberOfModules(dimension d) {
|
||||||
|
|
||||||
@ -2702,7 +2730,7 @@ int multiSlsDetector::getMaxNumberOfModules(dimension d) {
|
|||||||
|
|
||||||
for (int idet=0; idet<thisMultiDetector->numberOfDetectors; idet++) {
|
for (int idet=0; idet<thisMultiDetector->numberOfDetectors; idet++) {
|
||||||
if (detectors[idet]) {
|
if (detectors[idet]) {
|
||||||
ret1=detectors[idet]->getMaxNumberOfModules();
|
ret1=detectors[idet]->getMaxNumberOfModules(d);
|
||||||
ret+=ret1;
|
ret+=ret1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2743,14 +2771,14 @@ int multiSlsDetector::setNumberOfModules(int p, dimension d) {
|
|||||||
|
|
||||||
int multiSlsDetector::decodeNMod(int i, int &id, int &im) {
|
int multiSlsDetector::decodeNMod(int i, int &id, int &im) {
|
||||||
#ifdef VERBOSE
|
#ifdef VERBOSE
|
||||||
cout << " Module " << i << " belongs to detector ";
|
cout << " Module " << i << " belongs to detector " << id ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (i<0 || i>=getMaxNumberOfModules()) {
|
if (i<0 || i>=getMaxMods()) {
|
||||||
id=-1;
|
id=-1;
|
||||||
im=-1;
|
im=-1;
|
||||||
#ifdef VERBOSE
|
#ifdef VERBOSE
|
||||||
cout << id << " position " << im << endl;
|
cout << "A---------" << id << " position " << im << endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@ -2763,7 +2791,7 @@ int multiSlsDetector::decodeNMod(int i, int &id, int &im) {
|
|||||||
id=idet;
|
id=idet;
|
||||||
im=i;
|
im=i;
|
||||||
#ifdef VERBOSE
|
#ifdef VERBOSE
|
||||||
cout << id << " position " << im << endl;
|
cout << "B---------" <<id << " position " << im << endl;
|
||||||
#endif
|
#endif
|
||||||
return im;
|
return im;
|
||||||
} else {
|
} else {
|
||||||
@ -2774,7 +2802,7 @@ int multiSlsDetector::decodeNMod(int i, int &id, int &im) {
|
|||||||
id=-1;
|
id=-1;
|
||||||
im=-1;
|
im=-1;
|
||||||
#ifdef VERBOSE
|
#ifdef VERBOSE
|
||||||
cout << id << " position " << im << endl;
|
cout <<"C---------" << id << " position " << im << endl;
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -3426,9 +3454,12 @@ int multiSlsDetector::writeDataFile(string fname, int *data) {
|
|||||||
{
|
{
|
||||||
for (int i=0; i<thisMultiDetector->numberOfDetectors; i++) {
|
for (int i=0; i<thisMultiDetector->numberOfDetectors; i++) {
|
||||||
if (detectors[i]) {
|
if (detectors[i]) {
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << " write " << i << endl;
|
||||||
|
#endif
|
||||||
detectors[i]->writeDataFile(outfile, detectors[i]->getTotalNumberOfChannels(), data+off, choff);
|
detectors[i]->writeDataFile(outfile, detectors[i]->getTotalNumberOfChannels(), data+off, choff);
|
||||||
choff+=detectors[i]->getMaxNumberOfChannels();
|
choff+=detectors[i]->getMaxNumberOfChannels();
|
||||||
off+=detectors[i]->getTotalNumberOfChannels();
|
off+=detectors[i]->getTotalNumberOfChannels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,9 +288,10 @@ class multiSlsDetector : public slsDetectorUtils {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int getMaxMods();
|
||||||
int getNMods();
|
int getNMods();
|
||||||
int getChansPerMod(int imod=0);
|
int getChansPerMod(int imod=0);
|
||||||
|
|
||||||
angleConversionConstant *getAngularConversionPointer(int imod=0);
|
angleConversionConstant *getAngularConversionPointer(int imod=0);
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ int ififostart, ififostop, ififostep, ififo;
|
|||||||
|
|
||||||
int masterMode=NO_MASTER, syncMode=NO_SYNCHRONIZATION, timingMode=AUTO_TIMING;
|
int masterMode=NO_MASTER, syncMode=NO_SYNCHRONIZATION, timingMode=AUTO_TIMING;
|
||||||
|
|
||||||
enum externalSignalFlag signals[4]={EXT_SIG_OFF, EXT_SIG_OFF, EXT_SIG_OFF, EXT_SIG_OFF};
|
enum externalSignalFlag signals[4]={GATE_IN_ACTIVE_HIGH, TRIGGER_IN_RISING_EDGE, SIGNAL_OFF, SIGNAL_OFF};
|
||||||
|
|
||||||
|
|
||||||
#ifdef MCB_FUNCS
|
#ifdef MCB_FUNCS
|
||||||
|
@ -1380,7 +1380,7 @@ int slsDetector::getMaxNumberOfModules(dimension d){
|
|||||||
controlSocket->ReceiveDataOnly(&retval,sizeof(retval));
|
controlSocket->ReceiveDataOnly(&retval,sizeof(retval));
|
||||||
else {
|
else {
|
||||||
controlSocket->ReceiveDataOnly(mess,sizeof(mess));
|
controlSocket->ReceiveDataOnly(mess,sizeof(mess));
|
||||||
std::cout<< "Deterctor returned error: " << mess << std::endl;
|
std::cout<< "Detector returned error: " << mess << std::endl;
|
||||||
}
|
}
|
||||||
controlSocket->Disconnect();
|
controlSocket->Disconnect();
|
||||||
if (ret==FORCE_UPDATE)
|
if (ret==FORCE_UPDATE)
|
||||||
@ -4919,6 +4919,8 @@ int slsDetector::writeConfigurationFile(ofstream &outfile){
|
|||||||
|
|
||||||
slsDetectorCommand *cmd=new slsDetectorCommand(this);
|
slsDetectorCommand *cmd=new slsDetectorCommand(this);
|
||||||
int nvar;
|
int nvar;
|
||||||
|
int nsig=-1;
|
||||||
|
|
||||||
string names[]={ \
|
string names[]={ \
|
||||||
"hostname", \
|
"hostname", \
|
||||||
"port", \
|
"port", \
|
||||||
@ -4941,7 +4943,8 @@ int slsDetector::writeConfigurationFile(ofstream &outfile){
|
|||||||
"threaded", \
|
"threaded", \
|
||||||
"waitstates", \
|
"waitstates", \
|
||||||
"setlength", \
|
"setlength", \
|
||||||
"clkdivider"};
|
"clkdivider", \
|
||||||
|
"extsig" };
|
||||||
|
|
||||||
switch (thisDetector->myDetectorType) {
|
switch (thisDetector->myDetectorType) {
|
||||||
case GOTTHARD:
|
case GOTTHARD:
|
||||||
@ -4951,8 +4954,11 @@ int slsDetector::writeConfigurationFile(ofstream &outfile){
|
|||||||
names[9]="servermac";
|
names[9]="servermac";
|
||||||
nvar=10;
|
nvar=10;
|
||||||
break;
|
break;
|
||||||
|
case MYTHEN:
|
||||||
|
nsig=4;
|
||||||
default:
|
default:
|
||||||
nvar=22;
|
nvar=23;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int iv=0;
|
int iv=0;
|
||||||
@ -4963,8 +4969,16 @@ int slsDetector::writeConfigurationFile(ofstream &outfile){
|
|||||||
|
|
||||||
|
|
||||||
for (iv=0; iv<nvar; iv++) {
|
for (iv=0; iv<nvar; iv++) {
|
||||||
strcpy(args[0],names[iv].c_str());
|
cout << iv << " " << names[iv] << endl;
|
||||||
outfile << names[iv] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl;
|
if (names[iv]=="extsig") {
|
||||||
|
for (int is=0; is<nsig; is++) {
|
||||||
|
sprintf(args[0],"%s:%d",names[iv].c_str(),is);
|
||||||
|
outfile << names[iv] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strcpy(args[0],names[iv].c_str());
|
||||||
|
outfile << names[iv] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete cmd;
|
delete cmd;
|
||||||
return iv;
|
return iv;
|
||||||
@ -5030,7 +5044,7 @@ int slsDetector::dumpDetectorSetup(string const fname, int level){
|
|||||||
"badchannels",\
|
"badchannels",\
|
||||||
"angconv",\
|
"angconv",\
|
||||||
"trimbits",\
|
"trimbits",\
|
||||||
"extsig"
|
"timing"
|
||||||
};
|
};
|
||||||
int nvar=41;
|
int nvar=41;
|
||||||
int iv=0;
|
int iv=0;
|
||||||
@ -5103,10 +5117,11 @@ int slsDetector::dumpDetectorSetup(string const fname, int level){
|
|||||||
outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl;
|
outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl;
|
||||||
iv++;
|
iv++;
|
||||||
|
|
||||||
for (int is=0; is<4; is++) {
|
strcpy(args[0],names[iv].c_str());
|
||||||
sprintf(args[0],"%s:%d",names[iv].c_str(),is);
|
// for (int is=0; is<4; is++) {
|
||||||
|
// sprintf(args[0],"%s:%d",names[iv].c_str(),is);
|
||||||
outfile << args[0] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl;
|
outfile << args[0] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl;
|
||||||
}
|
// }
|
||||||
iv++;
|
iv++;
|
||||||
outfile.close();
|
outfile.close();
|
||||||
}
|
}
|
||||||
|
@ -36,21 +36,40 @@ angularConversion::~angularConversion(){
|
|||||||
|
|
||||||
|
|
||||||
float* angularConversion::convertAngles(float pos) {
|
float* angularConversion::convertAngles(float pos) {
|
||||||
int imod;
|
int imod=0;
|
||||||
float *ang=new float[getTotalNumberOfChannels()];
|
float *ang=new float[getTotalNumberOfChannels()];
|
||||||
float enc=pos;
|
float enc=pos;
|
||||||
angleConversionConstant *p=NULL;
|
angleConversionConstant *p=NULL;
|
||||||
for (int ip=0; ip<getTotalNumberOfChannels(); ip++) {
|
|
||||||
imod=ip/(getChansPerMod(0)); // always for module 0?????
|
|
||||||
p=getAngularConversionPointer(imod);
|
|
||||||
|
|
||||||
if (getMoveFlag(imod)==0)
|
int ch0=0;
|
||||||
enc=0;
|
int chlast=getChansPerMod(0);
|
||||||
else
|
int nchmod=getChansPerMod(0);
|
||||||
enc=pos;
|
p=getAngularConversionPointer(imod);
|
||||||
|
if (getMoveFlag(imod)==0)
|
||||||
|
enc=0;
|
||||||
|
else
|
||||||
|
enc=pos;
|
||||||
|
|
||||||
|
for (int ip=0; ip<getTotalNumberOfChannels(); ip++) {
|
||||||
|
#ifdef VERBOSE
|
||||||
|
// cout << "ip " << ip << " ch0 " << ch0 << " chlast " << chlast << " imod " << imod << endl;
|
||||||
|
#endif
|
||||||
|
if (ip>=chlast) {
|
||||||
|
imod++;
|
||||||
|
p=getAngularConversionPointer(imod);
|
||||||
|
if (getMoveFlag(imod)==0)
|
||||||
|
enc=0;
|
||||||
|
else
|
||||||
|
enc=pos;
|
||||||
|
|
||||||
|
ch0=chlast;
|
||||||
|
nchmod=getChansPerMod(imod);
|
||||||
|
if (nchmod>0)
|
||||||
|
chlast+=nchmod;
|
||||||
|
}
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
ang[ip]=angle(ip%(getChansPerMod()), \
|
ang[ip]=angle(ip-ch0, \
|
||||||
enc, \
|
enc, \
|
||||||
(*fineOffset)+(*globalOffset), \
|
(*fineOffset)+(*globalOffset), \
|
||||||
p->r_conversion, \
|
p->r_conversion, \
|
||||||
|
@ -417,8 +417,6 @@ class angularConversion : public virtual slsDetectorBase {
|
|||||||
current position of the detector
|
current position of the detector
|
||||||
*/
|
*/
|
||||||
float currentPosition;
|
float currentPosition;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
current position index of the detector
|
current position index of the detector
|
||||||
*/
|
*/
|
||||||
|
@ -137,15 +137,17 @@ void postProcessing::processFrame(int *myData, int delflag) {
|
|||||||
fname=createFileName();
|
fname=createFileName();
|
||||||
|
|
||||||
|
|
||||||
//uses static function?!?!?!?
|
//uses static function?!?!?!?
|
||||||
writeDataFile (fname+string(".raw"),fdata, NULL, NULL, 'i');
|
writeDataFile (fname+string(".raw"),fdata, NULL, NULL, 'i');
|
||||||
|
|
||||||
doProcessing(fdata,delflag, fname);
|
doProcessing(fdata,delflag, fname);
|
||||||
|
|
||||||
|
delete [] myData;
|
||||||
|
myData=NULL;
|
||||||
|
fdata=NULL;
|
||||||
|
|
||||||
delete [] myData;
|
|
||||||
myData=NULL;
|
|
||||||
#ifdef VERBOSE
|
#ifdef VERBOSE
|
||||||
// cout << "Pop data queue " << *fileIndex << endl;
|
cout << "Pop data queue " << *fileIndex << endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pthread_mutex_lock(&mp);
|
pthread_mutex_lock(&mp);
|
||||||
@ -159,7 +161,7 @@ void postProcessing::processFrame(int *myData, int delflag) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void postProcessing::doProcessing(float *fdata, int delflag, string fname) {
|
void postProcessing::doProcessing(float *lfdata, int delflag, string fname) {
|
||||||
|
|
||||||
|
|
||||||
/** write raw data file */
|
/** write raw data file */
|
||||||
@ -187,13 +189,13 @@ void postProcessing::doProcessing(float *fdata, int delflag, string fname) {
|
|||||||
if (*correctionMask&(1<<RATE_CORRECTION)) {
|
if (*correctionMask&(1<<RATE_CORRECTION)) {
|
||||||
rcdata=new float[getTotalNumberOfChannels()];
|
rcdata=new float[getTotalNumberOfChannels()];
|
||||||
rcerr=new float[getTotalNumberOfChannels()];
|
rcerr=new float[getTotalNumberOfChannels()];
|
||||||
rateCorrect(fdata,NULL,rcdata,rcerr);
|
rateCorrect(lfdata,NULL,rcdata,rcerr);
|
||||||
delete [] fdata;
|
delete [] lfdata;
|
||||||
fdata=NULL;
|
|
||||||
} else {
|
} else {
|
||||||
rcdata=fdata;
|
rcdata=lfdata;
|
||||||
fdata=NULL;
|
|
||||||
}
|
}
|
||||||
|
lfdata=NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -250,6 +252,7 @@ void postProcessing::doProcessing(float *fdata, int delflag, string fname) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
cout << "lock 1" << endl;
|
||||||
pthread_mutex_lock(&mp);
|
pthread_mutex_lock(&mp);
|
||||||
if ((getCurrentPositionIndex()>=getNumberOfPositions() && posfinished==1 && queuesize==1)) {
|
if ((getCurrentPositionIndex()>=getNumberOfPositions() && posfinished==1 && queuesize==1)) {
|
||||||
|
|
||||||
@ -259,6 +262,7 @@ void postProcessing::doProcessing(float *fdata, int delflag, string fname) {
|
|||||||
np=finalizeMerging();
|
np=finalizeMerging();
|
||||||
/** file writing */
|
/** file writing */
|
||||||
incrementPositionIndex();
|
incrementPositionIndex();
|
||||||
|
cout << "unlock 1" << endl;
|
||||||
pthread_mutex_unlock(&mp);
|
pthread_mutex_unlock(&mp);
|
||||||
|
|
||||||
|
|
||||||
@ -279,16 +283,21 @@ void postProcessing::doProcessing(float *fdata, int delflag, string fname) {
|
|||||||
} else {
|
} else {
|
||||||
thisData=new detectorData(getMergedCounts(),getMergedErrors(),getMergedPositions(),getCurrentProgress(),(fname+ext).c_str(),np);
|
thisData=new detectorData(getMergedCounts(),getMergedErrors(),getMergedPositions(),getCurrentProgress(),(fname+ext).c_str(),np);
|
||||||
|
|
||||||
|
cout << "lock 2" << endl;
|
||||||
pthread_mutex_lock(&mg);
|
pthread_mutex_lock(&mg);
|
||||||
finalDataQueue.push(thisData);
|
finalDataQueue.push(thisData);
|
||||||
|
cout << "unlock 2" << endl;
|
||||||
pthread_mutex_unlock(&mg);
|
pthread_mutex_unlock(&mg);
|
||||||
}
|
}
|
||||||
|
cout << "lock 3" << endl;
|
||||||
pthread_mutex_lock(&mp);
|
pthread_mutex_lock(&mp);
|
||||||
}
|
}
|
||||||
|
cout << "unlock 3" << endl;
|
||||||
pthread_mutex_unlock(&mp);
|
pthread_mutex_unlock(&mp);
|
||||||
|
|
||||||
if (ffcdata)
|
if (ffcdata)
|
||||||
delete [] ffcdata;
|
delete [] ffcdata;
|
||||||
|
|
||||||
ffcdata=NULL;
|
ffcdata=NULL;
|
||||||
|
|
||||||
if (ffcerr)
|
if (ffcerr)
|
||||||
@ -317,7 +326,9 @@ void postProcessing::doProcessing(float *fdata, int delflag, string fname) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
incrementFileIndex();
|
incrementFileIndex();
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << "fdata is " << fdata << endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,9 +460,15 @@ void* postProcessing::processData(int delflag) {
|
|||||||
dum=0;
|
dum=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fdata)
|
if (fdata) {
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << "delete fdata" << endl;
|
||||||
|
#endif
|
||||||
delete [] fdata;
|
delete [] fdata;
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << "done " << endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user