@@ -1,9 +1,6 | |||||
1 | import numpy |
|
1 | import numpy | |
2 | import math |
|
2 | import math | |
3 | from scipy import optimize |
|
3 | from scipy import optimize, interpolate, signal, stats, ndimage | |
4 | from scipy import interpolate |
|
|||
5 | from scipy import signal |
|
|||
6 | from scipy import stats |
|
|||
7 | import re |
|
4 | import re | |
8 | import datetime |
|
5 | import datetime | |
9 | import copy |
|
6 | import copy | |
@@ -12,7 +9,7 import importlib | |||||
12 | import itertools |
|
9 | import itertools | |
13 |
|
10 | |||
14 | from jroproc_base import ProcessingUnit, Operation |
|
11 | from jroproc_base import ProcessingUnit, Operation | |
15 | from schainpy.model.data.jrodata import Parameters |
|
12 | from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon | |
16 |
|
13 | |||
17 |
|
14 | |||
18 | class ParametersProc(ProcessingUnit): |
|
15 | class ParametersProc(ProcessingUnit): | |
@@ -53,13 +50,14 class ParametersProc(ProcessingUnit): | |||||
53 | self.dataOut.utctime = self.dataIn.utctime |
|
50 | self.dataOut.utctime = self.dataIn.utctime | |
54 | self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada |
|
51 | self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada | |
55 | self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip |
|
52 | self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip | |
56 |
|
|
53 | self.dataOut.nCohInt = self.dataIn.nCohInt | |
57 | # self.dataOut.nIncohInt = 1 |
|
54 | # self.dataOut.nIncohInt = 1 | |
58 | self.dataOut.ippSeconds = self.dataIn.ippSeconds |
|
55 | self.dataOut.ippSeconds = self.dataIn.ippSeconds | |
59 | # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter |
|
56 | # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter | |
60 | self.dataOut.timeInterval = self.dataIn.timeInterval |
|
57 | self.dataOut.timeInterval = self.dataIn.timeInterval | |
61 | self.dataOut.heightList = self.dataIn.getHeiRange() |
|
58 | self.dataOut.heightList = self.dataIn.getHeiRange() | |
62 | self.dataOut.frequency = self.dataIn.frequency |
|
59 | self.dataOut.frequency = self.dataIn.frequency | |
|
60 | self.dataOut.noise = self.dataIn.noise | |||
63 |
|
61 | |||
64 | def run(self): |
|
62 | def run(self): | |
65 |
|
63 | |||
@@ -77,7 +75,8 class ParametersProc(ProcessingUnit): | |||||
77 | #---------------------- Spectra Data --------------------------- |
|
75 | #---------------------- Spectra Data --------------------------- | |
78 |
|
76 | |||
79 | if self.dataIn.type == "Spectra": |
|
77 | if self.dataIn.type == "Spectra": | |
80 | self.dataOut.data_pre = self.dataIn.data_spc.copy() |
|
78 | ||
|
79 | self.dataOut.data_pre = (self.dataIn.data_spc,self.dataIn.data_cspc) | |||
81 | self.dataOut.abscissaList = self.dataIn.getVelRange(1) |
|
80 | self.dataOut.abscissaList = self.dataIn.getVelRange(1) | |
82 | self.dataOut.noise = self.dataIn.getNoise() |
|
81 | self.dataOut.noise = self.dataIn.getNoise() | |
83 | self.dataOut.normFactor = self.dataIn.normFactor |
|
82 | self.dataOut.normFactor = self.dataIn.normFactor | |
@@ -87,18 +86,21 class ParametersProc(ProcessingUnit): | |||||
87 | #---------------------- Correlation Data --------------------------- |
|
86 | #---------------------- Correlation Data --------------------------- | |
88 |
|
87 | |||
89 | if self.dataIn.type == "Correlation": |
|
88 | if self.dataIn.type == "Correlation": | |
90 | lagRRange = self.dataIn.lagR |
|
|||
91 | indR = numpy.where(lagRRange == 0)[0][0] |
|
|||
92 |
|
89 | |||
93 | self.dataOut.data_pre = self.dataIn.data_corr.copy()[:,:,indR,:] |
|
90 | if self.dataIn.data_ccf is not None: | |
94 |
self.dataOut. |
|
91 | self.dataOut.data_pre = (self.dataIn.data_acf,self.dataIn.data_ccf) | |
|
92 | else: | |||
|
93 | self.dataOut.data_pre = self.dataIn.data_acf.copy() | |||
|
94 | ||||
|
95 | self.dataOut.abscissaList = self.dataIn.lagRange | |||
95 | self.dataOut.noise = self.dataIn.noise |
|
96 | self.dataOut.noise = self.dataIn.noise | |
96 | self.dataOut.normFactor = self.dataIn.normFactor |
|
97 | self.dataOut.normFactor = self.dataIn.normFactor | |
97 | self.dataOut.data_SNR = self.dataIn.SNR |
|
98 | self.dataOut.data_SNR = self.dataIn.SNR | |
98 | self.dataOut.groupList = self.dataIn.pairsList |
|
99 | self.dataOut.groupList = self.dataIn.pairsList | |
99 | self.dataOut.flagNoData = False |
|
100 | self.dataOut.flagNoData = False | |
|
101 | self.dataOut.nAvg = self.dataIn.nAvg | |||
100 |
|
102 | |||
101 |
#---------------------- |
|
103 | #---------------------- Parameters Data --------------------------- | |
102 |
|
104 | |||
103 | if self.dataIn.type == "Parameters": |
|
105 | if self.dataIn.type == "Parameters": | |
104 | self.dataOut.copy(self.dataIn) |
|
106 | self.dataOut.copy(self.dataIn) | |
@@ -126,6 +128,7 class ParametersProc(ProcessingUnit): | |||||
126 | self.dataOut.data_SNR |
|
128 | self.dataOut.data_SNR | |
127 |
|
129 | |||
128 | ''' |
|
130 | ''' | |
|
131 | self.dataOut.data_pre = self.dataOut.data_pre[0] | |||
129 | data = self.dataOut.data_pre |
|
132 | data = self.dataOut.data_pre | |
130 | absc = self.dataOut.abscissaList[:-1] |
|
133 | absc = self.dataOut.abscissaList[:-1] | |
131 | noise = self.dataOut.noise |
|
134 | noise = self.dataOut.noise | |
@@ -1324,7 +1327,223 class ParametersProc(ProcessingUnit): | |||||
1324 | fmp=numpy.dot(LT,fm) |
|
1327 | fmp=numpy.dot(LT,fm) | |
1325 | chisq=numpy.dot((dp-fmp).T,(dp-fmp)) |
|
1328 | chisq=numpy.dot((dp-fmp).T,(dp-fmp)) | |
1326 | return chisq |
|
1329 | return chisq | |
|
1330 | ||||
|
1331 | def NonSpecularMeteorDetection(self, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False): | |||
|
1332 | data_acf = self.dataOut.data_pre[0] | |||
|
1333 | data_ccf = self.dataOut.data_pre[1] | |||
1327 |
|
1334 | |||
|
1335 | lamb = self.dataOut.C/self.dataOut.frequency | |||
|
1336 | tSamp = self.dataOut.ippSeconds*self.dataOut.nCohInt | |||
|
1337 | paramInterval = self.dataOut.paramInterval | |||
|
1338 | ||||
|
1339 | nChannels = data_acf.shape[0] | |||
|
1340 | nLags = data_acf.shape[1] | |||
|
1341 | nProfiles = data_acf.shape[2] | |||
|
1342 | nHeights = self.dataOut.nHeights | |||
|
1343 | nCohInt = self.dataOut.nCohInt | |||
|
1344 | sec = numpy.round(nProfiles/self.dataOut.paramInterval) | |||
|
1345 | heightList = self.dataOut.heightList | |||
|
1346 | ippSeconds = self.dataOut.ippSeconds*self.dataOut.nCohInt*self.dataOut.nAvg | |||
|
1347 | utctime = self.dataOut.utctime | |||
|
1348 | ||||
|
1349 | self.dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds) | |||
|
1350 | ||||
|
1351 | #------------------------ SNR -------------------------------------- | |||
|
1352 | power = data_acf[:,0,:,:].real | |||
|
1353 | noise = numpy.zeros(nChannels) | |||
|
1354 | SNR = numpy.zeros(power.shape) | |||
|
1355 | for i in range(nChannels): | |||
|
1356 | noise[i] = hildebrand_sekhon(power[i,:], nCohInt) | |||
|
1357 | SNR[i] = (power[i]-noise[i])/noise[i] | |||
|
1358 | SNRm = numpy.nanmean(SNR, axis = 0) | |||
|
1359 | SNRdB = 10*numpy.log10(SNR) | |||
|
1360 | ||||
|
1361 | if mode == 'SA': | |||
|
1362 | nPairs = data_ccf.shape[0] | |||
|
1363 | #---------------------- Coherence and Phase -------------------------- | |||
|
1364 | phase = numpy.zeros(data_ccf[:,0,:,:].shape) | |||
|
1365 | # phase1 = numpy.copy(phase) | |||
|
1366 | coh1 = numpy.zeros(data_ccf[:,0,:,:].shape) | |||
|
1367 | ||||
|
1368 | for p in range(nPairs): | |||
|
1369 | ch0 = self.dataOut.groupList[p][0] | |||
|
1370 | ch1 = self.dataOut.groupList[p][1] | |||
|
1371 | ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:]) | |||
|
1372 | phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter | |||
|
1373 | # phase1[p,:,:] = numpy.angle(ccf) #median filter | |||
|
1374 | coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter | |||
|
1375 | # coh1[p,:,:] = numpy.abs(ccf) #median filter | |||
|
1376 | coh = numpy.nanmax(coh1, axis = 0) | |||
|
1377 | # struc = numpy.ones((5,1)) | |||
|
1378 | # coh = ndimage.morphology.grey_dilation(coh, size=(10,1)) | |||
|
1379 | #---------------------- Radial Velocity ---------------------------- | |||
|
1380 | phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0) | |||
|
1381 | velRad = phaseAux*lamb/(4*numpy.pi*tSamp) | |||
|
1382 | ||||
|
1383 | if allData: | |||
|
1384 | boolMetFin = ~numpy.isnan(SNRm) | |||
|
1385 | # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0) | |||
|
1386 | else: | |||
|
1387 | #------------------------ Meteor mask --------------------------------- | |||
|
1388 | # #SNR mask | |||
|
1389 | # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB)) | |||
|
1390 | # | |||
|
1391 | # #Erase small objects | |||
|
1392 | # boolMet1 = self.__erase_small(boolMet, 2*sec, 5) | |||
|
1393 | # | |||
|
1394 | # auxEEJ = numpy.sum(boolMet1,axis=0) | |||
|
1395 | # indOver = auxEEJ>nProfiles*0.8 #Use this later | |||
|
1396 | # indEEJ = numpy.where(indOver)[0] | |||
|
1397 | # indNEEJ = numpy.where(~indOver)[0] | |||
|
1398 | # | |||
|
1399 | # boolMetFin = boolMet1 | |||
|
1400 | # | |||
|
1401 | # if indEEJ.size > 0: | |||
|
1402 | # boolMet1[:,indEEJ] = False #Erase heights with EEJ | |||
|
1403 | # | |||
|
1404 | # boolMet2 = coh > cohThresh | |||
|
1405 | # boolMet2 = self.__erase_small(boolMet2, 2*sec,5) | |||
|
1406 | # | |||
|
1407 | # #Final Meteor mask | |||
|
1408 | # boolMetFin = boolMet1|boolMet2 | |||
|
1409 | ||||
|
1410 | #Coherence mask | |||
|
1411 | boolMet1 = coh > 0.75 | |||
|
1412 | struc = numpy.ones((30,1)) | |||
|
1413 | boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc) | |||
|
1414 | ||||
|
1415 | #Derivative mask | |||
|
1416 | derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0) | |||
|
1417 | boolMet2 = derPhase < 0.2 | |||
|
1418 | # boolMet2 = ndimage.morphology.binary_opening(boolMet2) | |||
|
1419 | # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1))) | |||
|
1420 | boolMet2 = ndimage.median_filter(boolMet2,size=5) | |||
|
1421 | boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool))) | |||
|
1422 | # #Final mask | |||
|
1423 | # boolMetFin = boolMet2 | |||
|
1424 | boolMetFin = boolMet1&boolMet2 | |||
|
1425 | # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin) | |||
|
1426 | #Creating data_param | |||
|
1427 | coordMet = numpy.where(boolMetFin) | |||
|
1428 | ||||
|
1429 | tmet = coordMet[0] | |||
|
1430 | hmet = coordMet[1] | |||
|
1431 | ||||
|
1432 | data_param = numpy.zeros((tmet.size, 6 + nPairs)) | |||
|
1433 | data_param[:,0] = utctime | |||
|
1434 | data_param[:,1] = tmet | |||
|
1435 | data_param[:,2] = hmet | |||
|
1436 | data_param[:,3] = SNRm[tmet,hmet] | |||
|
1437 | data_param[:,4] = velRad[tmet,hmet] | |||
|
1438 | data_param[:,5] = coh[tmet,hmet] | |||
|
1439 | data_param[:,6:] = phase[:,tmet,hmet].T | |||
|
1440 | ||||
|
1441 | elif mode == 'DBS': | |||
|
1442 | self.dataOut.groupList = numpy.arange(nChannels) | |||
|
1443 | ||||
|
1444 | #Radial Velocities | |||
|
1445 | # phase = numpy.angle(data_acf[:,1,:,:]) | |||
|
1446 | phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1)) | |||
|
1447 | velRad = phase*lamb/(4*numpy.pi*tSamp) | |||
|
1448 | ||||
|
1449 | #Spectral width | |||
|
1450 | acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1)) | |||
|
1451 | acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1)) | |||
|
1452 | ||||
|
1453 | spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2)) | |||
|
1454 | # velRad = ndimage.median_filter(velRad, size = (1,5,1)) | |||
|
1455 | if allData: | |||
|
1456 | boolMetFin = ~numpy.isnan(SNRdB) | |||
|
1457 | else: | |||
|
1458 | #SNR | |||
|
1459 | boolMet1 = (SNRdB>SNRthresh) #SNR mask | |||
|
1460 | boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5)) | |||
|
1461 | ||||
|
1462 | #Radial velocity | |||
|
1463 | boolMet2 = numpy.abs(velRad) < 30 | |||
|
1464 | boolMet2 = ndimage.median_filter(boolMet2, (1,5,5)) | |||
|
1465 | ||||
|
1466 | #Spectral Width | |||
|
1467 | boolMet3 = spcWidth < 30 | |||
|
1468 | boolMet3 = ndimage.median_filter(boolMet3, (1,5,5)) | |||
|
1469 | # boolMetFin = self.__erase_small(boolMet1, 10,5) | |||
|
1470 | boolMetFin = boolMet1&boolMet2&boolMet3 | |||
|
1471 | ||||
|
1472 | #Creating data_param | |||
|
1473 | coordMet = numpy.where(boolMetFin) | |||
|
1474 | ||||
|
1475 | cmet = coordMet[0] | |||
|
1476 | tmet = coordMet[1] | |||
|
1477 | hmet = coordMet[2] | |||
|
1478 | ||||
|
1479 | data_param = numpy.zeros((tmet.size, 7)) | |||
|
1480 | data_param[:,0] = utctime | |||
|
1481 | data_param[:,1] = cmet | |||
|
1482 | data_param[:,2] = tmet | |||
|
1483 | data_param[:,3] = hmet | |||
|
1484 | data_param[:,4] = SNR[cmet,tmet,hmet].T | |||
|
1485 | data_param[:,5] = velRad[cmet,tmet,hmet].T | |||
|
1486 | data_param[:,6] = spcWidth[cmet,tmet,hmet].T | |||
|
1487 | ||||
|
1488 | # self.dataOut.data_param = data_int | |||
|
1489 | if len(data_param) == 0: | |||
|
1490 | self.dataOut.flagNoData = True | |||
|
1491 | else: | |||
|
1492 | self.dataOut.data_param = data_param | |||
|
1493 | ||||
|
1494 | def __erase_small(self, binArray, threshX, threshY): | |||
|
1495 | labarray, numfeat = ndimage.measurements.label(binArray) | |||
|
1496 | binArray1 = numpy.copy(binArray) | |||
|
1497 | ||||
|
1498 | for i in range(1,numfeat + 1): | |||
|
1499 | auxBin = (labarray==i) | |||
|
1500 | auxSize = auxBin.sum() | |||
|
1501 | ||||
|
1502 | x,y = numpy.where(auxBin) | |||
|
1503 | widthX = x.max() - x.min() | |||
|
1504 | widthY = y.max() - y.min() | |||
|
1505 | ||||
|
1506 | #width X: 3 seg -> 12.5*3 | |||
|
1507 | #width Y: | |||
|
1508 | ||||
|
1509 | if (auxSize < 50) or (widthX < threshX) or (widthY < threshY): | |||
|
1510 | binArray1[auxBin] = False | |||
|
1511 | ||||
|
1512 | return binArray1 | |||
|
1513 | ||||
|
1514 | def WeirdEcho(self): | |||
|
1515 | # data_pre = self.dataOut.data_pre | |||
|
1516 | # nHeights = self.dataOut.nHeights | |||
|
1517 | # # nProfiles = self.dataOut.data_pre.shape[1] | |||
|
1518 | # # data_param = numpy.zeros((len(pairslist),nProfiles,nHeights)) | |||
|
1519 | # data_param = numpy.zeros((len(pairslist),nHeights)) | |||
|
1520 | # | |||
|
1521 | # for i in range(len(pairslist)): | |||
|
1522 | # chan0 = data_pre[pairslist[i][0],:] | |||
|
1523 | # chan1 = data_pre[pairslist[i][1],:] | |||
|
1524 | # #calcular correlacion cruzada | |||
|
1525 | # #magnitud es coherencia | |||
|
1526 | # #fase es dif fase | |||
|
1527 | # correl = chan0*numpy.conj(chan1) | |||
|
1528 | # coherence = numpy.abs(correl)/(numpy.abs(chan0)*numpy.abs(chan1)) | |||
|
1529 | # phase = numpy.angle(correl) | |||
|
1530 | # # data_param[2*i,:,:] = coherence | |||
|
1531 | # data_param[i,:] = phase | |||
|
1532 | # | |||
|
1533 | # self.dataOut.data_param = data_param | |||
|
1534 | # self.dataOut.groupList = pairslist | |||
|
1535 | data_cspc = self.dataOut.data_pre[1] | |||
|
1536 | ccf = numpy.average(data_cspc,axis=1) | |||
|
1537 | phases = numpy.angle(ccf).T | |||
|
1538 | ||||
|
1539 | meteorOps = MeteorOperations() | |||
|
1540 | pairsList = ((0,1),(2,3)) | |||
|
1541 | jph = numpy.array([0,0,0,0]) | |||
|
1542 | AOAthresh = numpy.pi/8 | |||
|
1543 | azimuth = 45 | |||
|
1544 | error = numpy.zeros((phases.shape[0],1)) | |||
|
1545 | AOA,error = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth) | |||
|
1546 | self.dataOut.data_param = AOA.T | |||
1328 |
|
1547 | |||
1329 | class WindProfiler(Operation): |
|
1548 | class WindProfiler(Operation): | |
1330 |
|
1549 | |||
@@ -1647,6 +1866,165 class WindProfiler(Operation): | |||||
1647 |
|
1866 | |||
1648 | return winds, heightPerI[:-1] |
|
1867 | return winds, heightPerI[:-1] | |
1649 |
|
1868 | |||
|
1869 | def techniqueNSM_SA(self, **kwargs): | |||
|
1870 | metArray = kwargs['metArray'] | |||
|
1871 | heightList = kwargs['heightList'] | |||
|
1872 | timeList = kwargs['timeList'] | |||
|
1873 | ||||
|
1874 | rx_location = kwargs['rx_location'] | |||
|
1875 | groupList = kwargs['groupList'] | |||
|
1876 | azimuth = kwargs['azimuth'] | |||
|
1877 | dfactor = kwargs['dfactor'] | |||
|
1878 | k = kwargs['k'] | |||
|
1879 | ||||
|
1880 | azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth) | |||
|
1881 | d = dist*dfactor | |||
|
1882 | #Phase calculation | |||
|
1883 | metArray1 = self.__getPhaseSlope(metArray, heightList, timeList) | |||
|
1884 | ||||
|
1885 | metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities | |||
|
1886 | ||||
|
1887 | velEst = numpy.zeros((heightList.size,2))*numpy.nan | |||
|
1888 | azimuth1 = azimuth1*numpy.pi/180 | |||
|
1889 | ||||
|
1890 | for i in range(heightList.size): | |||
|
1891 | h = heightList[i] | |||
|
1892 | indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0] | |||
|
1893 | metHeight = metArray1[indH,:] | |||
|
1894 | if metHeight.shape[0] >= 2: | |||
|
1895 | velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities | |||
|
1896 | iazim = metHeight[:,1].astype(int) | |||
|
1897 | azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths | |||
|
1898 | A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux))) | |||
|
1899 | A = numpy.asmatrix(A) | |||
|
1900 | A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose() | |||
|
1901 | velHor = numpy.dot(A1,velAux) | |||
|
1902 | ||||
|
1903 | velEst[i,:] = numpy.squeeze(velHor) | |||
|
1904 | return velEst | |||
|
1905 | ||||
|
1906 | def __getPhaseSlope(self, metArray, heightList, timeList): | |||
|
1907 | meteorList = [] | |||
|
1908 | #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2 | |||
|
1909 | #Putting back together the meteor matrix | |||
|
1910 | utctime = metArray[:,0] | |||
|
1911 | uniqueTime = numpy.unique(utctime) | |||
|
1912 | ||||
|
1913 | phaseDerThresh = 0.5 | |||
|
1914 | ippSeconds = timeList[1] - timeList[0] | |||
|
1915 | sec = numpy.where(timeList>1)[0][0] | |||
|
1916 | nPairs = metArray.shape[1] - 6 | |||
|
1917 | nHeights = len(heightList) | |||
|
1918 | ||||
|
1919 | for t in uniqueTime: | |||
|
1920 | metArray1 = metArray[utctime==t,:] | |||
|
1921 | # phaseDerThresh = numpy.pi/4 #reducir Phase thresh | |||
|
1922 | tmet = metArray1[:,1].astype(int) | |||
|
1923 | hmet = metArray1[:,2].astype(int) | |||
|
1924 | ||||
|
1925 | metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1)) | |||
|
1926 | metPhase[:,:] = numpy.nan | |||
|
1927 | metPhase[:,hmet,tmet] = metArray1[:,6:].T | |||
|
1928 | ||||
|
1929 | #Delete short trails | |||
|
1930 | metBool = ~numpy.isnan(metPhase[0,:,:]) | |||
|
1931 | heightVect = numpy.sum(metBool, axis = 1) | |||
|
1932 | metBool[heightVect<sec,:] = False | |||
|
1933 | metPhase[:,heightVect<sec,:] = numpy.nan | |||
|
1934 | ||||
|
1935 | #Derivative | |||
|
1936 | metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1]) | |||
|
1937 | phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh)) | |||
|
1938 | metPhase[phDerAux] = numpy.nan | |||
|
1939 | ||||
|
1940 | #--------------------------METEOR DETECTION ----------------------------------------- | |||
|
1941 | indMet = numpy.where(numpy.any(metBool,axis=1))[0] | |||
|
1942 | ||||
|
1943 | for p in numpy.arange(nPairs): | |||
|
1944 | phase = metPhase[p,:,:] | |||
|
1945 | phDer = metDer[p,:,:] | |||
|
1946 | ||||
|
1947 | for h in indMet: | |||
|
1948 | height = heightList[h] | |||
|
1949 | phase1 = phase[h,:] #82 | |||
|
1950 | phDer1 = phDer[h,:] | |||
|
1951 | ||||
|
1952 | phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap | |||
|
1953 | ||||
|
1954 | indValid = numpy.where(~numpy.isnan(phase1))[0] | |||
|
1955 | initMet = indValid[0] | |||
|
1956 | endMet = 0 | |||
|
1957 | ||||
|
1958 | for i in range(len(indValid)-1): | |||
|
1959 | ||||
|
1960 | #Time difference | |||
|
1961 | inow = indValid[i] | |||
|
1962 | inext = indValid[i+1] | |||
|
1963 | idiff = inext - inow | |||
|
1964 | #Phase difference | |||
|
1965 | phDiff = numpy.abs(phase1[inext] - phase1[inow]) | |||
|
1966 | ||||
|
1967 | if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor | |||
|
1968 | sizeTrail = inow - initMet + 1 | |||
|
1969 | if sizeTrail>3*sec: #Too short meteors | |||
|
1970 | x = numpy.arange(initMet,inow+1)*ippSeconds | |||
|
1971 | y = phase1[initMet:inow+1] | |||
|
1972 | ynnan = ~numpy.isnan(y) | |||
|
1973 | x = x[ynnan] | |||
|
1974 | y = y[ynnan] | |||
|
1975 | slope, intercept, r_value, p_value, std_err = stats.linregress(x,y) | |||
|
1976 | ylin = x*slope + intercept | |||
|
1977 | rsq = r_value**2 | |||
|
1978 | if rsq > 0.5: | |||
|
1979 | vel = slope#*height*1000/(k*d) | |||
|
1980 | estAux = numpy.array([utctime,p,height, vel, rsq]) | |||
|
1981 | meteorList.append(estAux) | |||
|
1982 | initMet = inext | |||
|
1983 | metArray2 = numpy.array(meteorList) | |||
|
1984 | ||||
|
1985 | return metArray2 | |||
|
1986 | ||||
|
1987 | def __calculateAzimuth1(self, rx_location, pairslist, azimuth0): | |||
|
1988 | ||||
|
1989 | azimuth1 = numpy.zeros(len(pairslist)) | |||
|
1990 | dist = numpy.zeros(len(pairslist)) | |||
|
1991 | ||||
|
1992 | for i in range(len(rx_location)): | |||
|
1993 | ch0 = pairslist[i][0] | |||
|
1994 | ch1 = pairslist[i][1] | |||
|
1995 | ||||
|
1996 | diffX = rx_location[ch0][0] - rx_location[ch1][0] | |||
|
1997 | diffY = rx_location[ch0][1] - rx_location[ch1][1] | |||
|
1998 | azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi | |||
|
1999 | dist[i] = numpy.sqrt(diffX**2 + diffY**2) | |||
|
2000 | ||||
|
2001 | azimuth1 -= azimuth0 | |||
|
2002 | return azimuth1, dist | |||
|
2003 | ||||
|
2004 | def techniqueNSM_DBS(self, **kwargs): | |||
|
2005 | metArray = kwargs['metArray'] | |||
|
2006 | heightList = kwargs['heightList'] | |||
|
2007 | timeList = kwargs['timeList'] | |||
|
2008 | zenithList = kwargs['zenithList'] | |||
|
2009 | nChan = numpy.max(cmet) + 1 | |||
|
2010 | nHeights = len(heightList) | |||
|
2011 | ||||
|
2012 | utctime = metArray[:,0] | |||
|
2013 | cmet = metArray[:,1] | |||
|
2014 | hmet = metArray1[:,3].astype(int) | |||
|
2015 | h1met = heightList[hmet]*zenithList[cmet] | |||
|
2016 | vmet = metArray1[:,5] | |||
|
2017 | ||||
|
2018 | for i in range(nHeights - 1): | |||
|
2019 | hmin = heightList[i] | |||
|
2020 | hmax = heightList[i + 1] | |||
|
2021 | ||||
|
2022 | vthisH = vmet[(h1met>=hmin) & (h1met<hmax)] | |||
|
2023 | ||||
|
2024 | ||||
|
2025 | ||||
|
2026 | return data_output | |||
|
2027 | ||||
1650 | def run(self, dataOut, technique, **kwargs): |
|
2028 | def run(self, dataOut, technique, **kwargs): | |
1651 |
|
2029 | |||
1652 | param = dataOut.data_param |
|
2030 | param = dataOut.data_param | |
@@ -1684,7 +2062,7 class WindProfiler(Operation): | |||||
1684 | velRadial0 = param[:,1,:] #Radial velocity |
|
2062 | velRadial0 = param[:,1,:] #Radial velocity | |
1685 | dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(velRadial0, theta_x, theta_y, azimuth, correctFactor, horizontalOnly, heightList, SNR) #DBS Function |
|
2063 | dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(velRadial0, theta_x, theta_y, azimuth, correctFactor, horizontalOnly, heightList, SNR) #DBS Function | |
1686 | dataOut.utctimeInit = dataOut.utctime |
|
2064 | dataOut.utctimeInit = dataOut.utctime | |
1687 |
dataOut.outputInterval = dataOut. |
|
2065 | dataOut.outputInterval = dataOut.paramInterval | |
1688 |
|
2066 | |||
1689 | elif technique == 'SA': |
|
2067 | elif technique == 'SA': | |
1690 |
|
2068 | |||
@@ -1760,12 +2138,75 class WindProfiler(Operation): | |||||
1760 | dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax) |
|
2138 | dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax) | |
1761 | dataOut.flagNoData = False |
|
2139 | dataOut.flagNoData = False | |
1762 | self.__buffer = None |
|
2140 | self.__buffer = None | |
|
2141 | ||||
|
2142 | elif technique == 'Meteors1': | |||
|
2143 | dataOut.flagNoData = True | |||
|
2144 | self.__dataReady = False | |||
|
2145 | ||||
|
2146 | if kwargs.has_key('nMins'): | |||
|
2147 | nMins = kwargs['nMins'] | |||
|
2148 | else: nMins = 20 | |||
|
2149 | if kwargs.has_key('rx_location'): | |||
|
2150 | rx_location = kwargs['rx_location'] | |||
|
2151 | else: rx_location = [(0,1),(1,1),(1,0)] | |||
|
2152 | if kwargs.has_key('azimuth'): | |||
|
2153 | azimuth = kwargs['azimuth'] | |||
|
2154 | else: azimuth = 51 | |||
|
2155 | if kwargs.has_key('dfactor'): | |||
|
2156 | dfactor = kwargs['dfactor'] | |||
|
2157 | if kwargs.has_key('mode'): | |||
|
2158 | mode = kwargs['mode'] | |||
|
2159 | else: mode = 'SA' | |||
|
2160 | ||||
|
2161 | #Borrar luego esto | |||
|
2162 | if dataOut.groupList == None: | |||
|
2163 | dataOut.groupList = [(0,1),(0,2),(1,2)] | |||
|
2164 | groupList = dataOut.groupList | |||
|
2165 | C = 3e8 | |||
|
2166 | freq = 50e6 | |||
|
2167 | lamb = C/freq | |||
|
2168 | k = 2*numpy.pi/lamb | |||
|
2169 | ||||
|
2170 | timeList = dataOut.abscissaList | |||
|
2171 | heightList = dataOut.heightList | |||
|
2172 | ||||
|
2173 | if self.__isConfig == False: | |||
|
2174 | dataOut.outputInterval = nMins*60 | |||
|
2175 | # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03) | |||
|
2176 | #Get Initial LTC time | |||
|
2177 | initime = datetime.datetime.utcfromtimestamp(dataOut.utctime) | |||
|
2178 | minuteAux = initime.minute | |||
|
2179 | minuteNew = int(numpy.floor(minuteAux/nMins)*nMins) | |||
|
2180 | self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds() | |||
|
2181 | ||||
|
2182 | self.__isConfig = True | |||
|
2183 | ||||
|
2184 | if self.__buffer == None: | |||
|
2185 | self.__buffer = dataOut.data_param | |||
|
2186 | self.__firstdata = copy.copy(dataOut) | |||
|
2187 | ||||
|
2188 | else: | |||
|
2189 | self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param)) | |||
|
2190 | ||||
|
2191 | self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready | |||
|
2192 | ||||
|
2193 | if self.__dataReady: | |||
|
2194 | dataOut.utctimeInit = self.__initime | |||
|
2195 | self.__initime += dataOut.outputInterval #to erase time offset | |||
|
2196 | ||||
|
2197 | metArray = self.__buffer | |||
|
2198 | if mode == 'SA': | |||
|
2199 | dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList) | |||
|
2200 | elif mode == 'DBS': | |||
|
2201 | dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList) | |||
|
2202 | dataOut.data_output = dataOut.data_output.T | |||
|
2203 | dataOut.flagNoData = False | |||
|
2204 | self.__buffer = None | |||
1763 |
|
2205 | |||
1764 | return |
|
2206 | return | |
1765 |
|
2207 | |||
1766 | class EWDriftsEstimation(Operation): |
|
2208 | class EWDriftsEstimation(Operation): | |
1767 |
|
2209 | |||
1768 |
|
||||
1769 | def __init__(self): |
|
2210 | def __init__(self): | |
1770 | Operation.__init__(self) |
|
2211 | Operation.__init__(self) | |
1771 |
|
2212 | |||
@@ -2050,7 +2491,7 class MeteorOperations(): | |||||
2050 |
|
2491 | |||
2051 | return arrayParameters |
|
2492 | return arrayParameters | |
2052 |
|
2493 | |||
2053 |
def |
|
2494 | def getAOA(self, phases, pairsList, error, AOAthresh, azimuth): | |
2054 |
|
2495 | |||
2055 | arrayAOA = numpy.zeros((phases.shape[0],3)) |
|
2496 | arrayAOA = numpy.zeros((phases.shape[0],3)) | |
2056 | cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList) |
|
2497 | cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList) |
General Comments 0
You need to be logged in to leave comments.
Login now